粘包问题已经在上一篇博客中写到具体可以看-----------
以下是利用分包解决粘包问题的步骤:
-
消息长度前缀: 在每个数据包前加入消息长度信息。
-
定义协议格式: 明确定义通信协议的格式,包括消息头和消息体。
-
封包: 将数据按照协议格式封装成完整的数据包。
-
解包: 根据协议格式从接收到的字节流中解析出完整的数据包。
-
处理残余数据: 保留可能存在的残余数据,并在下一次接收到数据时继续解析。
-
错误处理: 考虑数据包丢失、损坏或乱序等特殊情况,实现相应的错误处理机制。
-
测试和优化: 进行测试以确保系统在不同条件下正常运行,优化协议和分包处理性能
怎么解决粘包问题呢,其实借鉴一下tcp报文段的组成(分成TCP数据部分和TCP首部),我们也可以把发送的数据分为两个部分,一个是data,一个是data_len,这样有了data_len之后可以保证接收到完整的data数据后不再接受数据,这样就解决了粘包的问题。
看见如下图,client端发送的hi 和 jack没有粘在一块成hijack:
server:
int total_len=0;int len=0; char buffer[1024];while ((len=read(client_sock,buffer+total_len,sizeof(buffer)-total_len))>0){total_len+=len;while (total_len>=sizeof(int)){int data_len=*(int *)buffer;if(total_len>=sizeof(int)+data_len){char data[1024];memmove(data,buffer+sizeof(int),data_len);data[data_len]='\0';std::cout<<"Received msg :"<<data<<std::endl;total_len-=sizeof(int)+data_len;memmove(buffer,buffer+sizeof(int)+data_len,total_len);}else{break;}} }
client:
std::string msg1="hi";std::string msg2="jack";char data1[256];*(int*)(data1)=msg1.length();int len=sizeof(int);memmove(data1+len,msg1.c_str(),msg1.length());if(write(client_sock,data1,len+msg1.length())==-1){std::cerr<<"Faild to write "<<std::endl;return -1;}char data2[256];*(int*)(data2)=msg2.length();int len2=sizeof(int);memmove(data2+len,msg2.c_str(),msg2.length());if(write(client_sock,data2,len2+msg2.length())==-1){std::cerr<<"Faild to write "<<std::endl;return -1;}