c++ 网络编程与协议的设计方法

1.TCP协议的粘包问题

TCP协议发送的是字节流,前后之间的间隔在哪里是不确定的,所有有可能出现粘包现象。

解决粘包问题主要有三个办法

(1).发送固定长度的包,这样接受方也接受固定长度,很显然这种办法很死板。

(2).指定字符串位为包的结束标志。这种方法有FTP和SMPT协议采用。

(3).使用包头+包体的方法。这种格式的包一般分为两个部分,包头和包体,包头是固定大小的,且包头必须包含一个字段来说明接下来的包体有多大。比如:

struct msg_header{

        int32_t bodysize;//指定包头的大小

        int32_t cmd;

};

这样包头的大小是固定的,为sizeof(struct msg_header),协议中需要先接受包头的大小,然后解析包头,根据解析出来的信息,来接受后面的包体,这样就组成了一个完整的包来处理。

2.解包和处理

       如果协议是包头+包体的方式(其他两种方式其实也一样)

       收到数据后,先接受包头,判断数据是否是包头大小,如果没有,则退出;如果有,则解析包头,计算接下来需要接受包体的大小。接受数据,判断数据是否达到要求,如果没有则退出,如果有则解析包体。

       这里面有一些细节问题,比如取出包头不要把包头从缓存区中取出来,而是复制出来,因为如果剩余的空间不足以存放包体大小,我们还得做扩充处理,然后把包体放回去。也就是说,我们每次取出数据的时候,最好是把包体和包头一起取出来,清空缓存。

     接受包头,解析包体要放在一个循环体里面!因为包太多,我们没办法同时处理多个包。

3.TLV

如果我们使用struct方法来处理TLV,则会发生格式过于死板的问题,后续版本的更新会很难进行。为了兼容版本,同时节省空间,获得更加灵活的协议,于是出现了TLV(type length value)协议,就是再每一个字段前面加一个类型字段。

struct msg_TLV{

        short type1;

        int version;

        short type2;

        char name[10];

};

这样我们可以根据type来判断后面的字段,协议就变得十分灵活

缺点就是多了一个类型字段,占据的空间变大了,还要判断类型,解析后面的信息。

你可能感兴趣的:(网络,tcp/ip,网络协议)