-
Notifications
You must be signed in to change notification settings - Fork 2.5k
KCP Best Practice EN
I suppose each different network layer should do different things, For FEC, there are to many algorithms, such as:
-
repeat
: as your reference -
xor
: p1 = m1, p2 = m2, p3 = m3, p4 = m1 ^ m2 ^ m3, any packet of p1-p4 can be recovered by xor other three together. -
Reed Solomon
: a little more complex but more powerful thanrepeat
andxor
Which one should I intergrate ? just can't decide easily. The main idea of protocol layer is you can assemble different layers together to fit your need.
for example KCP is just ARQ layer, and you can implement your own fec layer and connect them to kcp like this:
- initialize the KCP output callback function to your FEC send api.
- when a packet is decoded from your FEC layer (fec_recv), input it to KCP by
ikcp_input()
In my own projects, I have implemented my own reed solomon fec algorithm and make it cooperative with KCP like these.
also, you can make your own encryption layer.
for simplicity, you can integrate KCP to your TCP server:
- client should connect to your tcp port at first
- after login successful, server will send the udp address:port and conv id to client from tcp
- client send udp packets to server use the conv id and udp address:port.
- server verify the conv id and knows it is the same client just login successfully from tcp.
And than, FEC and encryption could be implemented inside this connection management layer
.
Since UDP is not always available in some ISP or company nat, in that case, you can still use tcp connections.
The encryption layer usually need add some bytes in the packet header when encoding. and FEC layer need add some bytes in the packet header too. To avoid frequently invoking memcpy you can introduce a skbuf like data structure:
There are some methods in your skbuf:
void head_push_uint8(uint8_t x);
void head_push_uint16(uint16_t x);
void head_push_uint32(uint32_t x);
uint8_t head_pop_uint8();
uint16_t head_pop_uint16();
uint32_t head_pop_uint32();
...
void tail_push_uint8(uint8_t x);
...
uint32_t tail_pop_uint32();
It allows you to add bytes in the header without memcpy. So there is only one memcpy required in the whole stack (copy data to skbuf in your kcp output callback function).