首先要明确,粘包问题中的 “包” ,是指的应用层的数据包。 在TCP的协议头中,没有如同UDP一样的 “报文长度” 这样的字段,但是有一个序号这样的字段。 站在传输层的角度,TCP是一个一个报文过来的。按照序号排好序放在缓冲区中。 站在应用层的角度,看到的只是一串连续的字节数据。 那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个完整的应用层数据包。 那么如何避免粘包问题呢?归根结底就是一句话,明确两个包之间的边界。
对于定长的包,保证每次都按固定大小读取即可;例如上面的Request结构,是固定大小的,那么就从缓冲区从头开始按sizeof(Request)依次读取即可;对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可);
对于UDP协议来说,是否也存在 “粘包问题” 呢? 对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在。同时,UDP是一个一个把数据交付给应用层。就有很明确的数据边界。 站在应用层的站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收。不会出现"半个"的情况。
|