tcp粘包的问题
tcp是是流式的传输协议, 基于这特点就会导致数据传输的时候造成粘包的现象。
什么是粘包
tcp传输时,因为网络环境的原因不会每一次发送的数据都是既定的大小,若每一个数据块是1k,那么发送过去就可能是很多个1k的包同时发送到对端,如果再加上其中每一个包的大小不同的时候,那么将无法进行数据包的划分,也就无法进行数据的解析。
粘包产生的原因
- 发送的数据的量
- 发送端和接收端对数据的处理速度
- 网络原因
粘包的解决方案
-
在发送一个数据块的头部先发送一个固定大小的整型数据,这个整型数据存的是数据块的字节数。(常用)
|100|字符串……|
100表示后面的字符串有100个字节这么大。
-
在每一个数据块的尾部添加一个特殊字符。
- 因为此时只能一个字符一个字符的读数据,不能一个块一个块的读,所以此时的效率有所降低,不常使用。
-
使用应用层的协议来收发数据,根据既定的协议可以解析出来数据。例如:http协议。
实例
-
发送端
int head = 0; char buf[1024]; //其中存放了一些有效数据 head = strlen(buf); //将两个数据块组合 //首先需要将head从小端字节序转换为大端字节序 head = htonl(head); char tmp[2048]; memcpy(tmp, head, 4); memcpy(tmp+4, buf, strlen(buf)); send(sock, tmp, strlen(tmp), 0);
-
接收端
string recvMsg { char tmp[5] = {0}; recv(sock, tmp, 4, 0); //得到4个字节的头后,将大端字节序转换为小端字节序 int len = ntohl(*(int*)tmp); //基于这个长度申请内存 char* data = (char*)malloc(len); recv(sock, buf, len, 0); string msg = string(data, len); free(data); return msg; }