首页 > 编程知识 正文

梦魇的原因及解决办法,tcp粘包通用处理方法

时间:2023-05-05 15:46:23 阅读:16061 作者:3901

1、粘包概念粘包:多个数据包连续存储在连续缓存中,对数据包进行读取时无法确定发生方的发送边界采用某一估测值大小为数据

例如,发送端发送两个数据,接收端一次接收一个半数据(接收端可能不知道一个分组的大小)。

2、tcp、udp消息最大长度ip消息:

tcp消息:

udp消息:

ip和udp都有16位长度字段,理论上ip和udp消息的最大负载长度必须为2 ^ 16,64kb,但tcp没有长度字段,理论上必须与ip相同。

但是,http://www.Sina.com/:存在称为最大传输单元(MTU )的其他限制,其限制了ip消息长度,在ip消息长度大于MTU的情况下通常设定为1500字节。双方的size不一致:tcp协议具有最大消息长度(MSS ),tcp通常将数据划分成MSS长度的块。 通常,MTU(1500 )-IP包头(20 )-TCP数据段的包头) 20 )=1460字节。

因此,tcp一次最多需要传输1460字节的数据。

3、粘包原因粘包现象的原因是多方面的,它既可能源于发送端,也可能源于接收端。

发送方引起的数据包是由TCP协议本身引起的:

TCP为了提高传输效率,发送侧经常在收集到足够的数据后发送一个分组的数据。 如果连续发送的数据很少,则TCP通常会根据优化算法将这些数据集中在一个数据包中发送一次,接收方会接收数据包数据。

TCP协议中规定了MSS,如果数据包太长,则会分别传输。 这样,接收方收到了数据包数据。 接收方引发的分组是分组粘合的现象,因为接收方用户进程没有立即接收数据。 它将接收方首先接收的数据放在系统接收缓冲器中,用户进程从该缓冲器接收数据,如果在下一个分组数据到达时用户进程没有获取上一个分组数据,则下一个分组数据被系统接收这是因为用户进程根据预设的缓冲器大小通过从系统接收缓冲器接收数据从而一次接收多个分组数据。

代码中常见的表达方式:

如果要发送的数据大于TCP发送缓冲区的可用空间,则会发生数据包损坏。 如果要发送的数据大于MSS,则TCP将在传输前打开包装。 如果要发送的数据小于TCP发送缓冲区的大小,则TCP会一次发送多次写入缓冲区的数据,从而导致数据包粘贴。 接收方的APP应用层无法立即读取接收缓冲区中的数据,导致数据包粘贴。

等等。 4、数据包的处理方式)当时的短连接的情况下,即使不考虑发送数据包的情况,如果数据没有如文件传送那样被结构化,发送侧只要进行发送,接收侧接收并保存就可以了。 另外,在接收到分组后,通过读取分组首部的长度字段,在双方建立了长连接的情况下,需要在连接后不久发送不同结构的数据的发送端将各个分组封装为固定长度,不足的填充0 据此,接收端每次从接收缓冲器读取固定长度的数据时,能够自然地分割各个数据包。 可以在数据包之间设置边界,例如添加特殊符号。 因此,接收端可以通过该边界分割不同的数据包。

等等。 在线课程学习中看到的指定数据长度的解决方法、主要想法:

数据结构中有一个表示长度(消息标题)的成员。 足够大的消息缓冲区)程序中为1024000字节),并重用套接字上的recv一次最多读取102400字节,然后重用后将接收到的消息连接到消息缓冲区。 将接收完整的消息,直到接收到的消息大于消息标头所示的长度。)。 因此,消息缓冲器

主要代码:

//缓冲区的最小单元格大小# ifndef recv _ buff _ szie # define recv _ buff _ szie 102400 # endif//! RECV_BUFF_SZIE//第二缓冲消息缓冲区char _ szmsgbuf [ recv _ buff _ szie * 10 ]={ }; //消息缓冲器的数据末尾位置int _lastPos=0; //接收缓冲区char _szRecv[RECV_BUFF_SZIE]={}; //接收数据处理包分割包intrecvdata(socketCSOCK )//5接收数据intnlen=) int (recv ) CSOCK、_szRecv、RECV_BUFF_SZIE、 //printf(nLen=%d(n ),nlen ); if(nlen=0) printf ) ' socket=%d与服务器断开连接,任务终止。 n ',cSock; 返回- 1; //将收到的数据转换为消息缓冲区memcpy(szmsgbuf_lastpos,_szRecv,nLen ); //将消息缓冲区的数据末尾位置向后移动_lastPos =nLen; //消息缓冲区的数据长度为标头DataHeader的长度while(lastpos=sizeof ) DataHeader ) /此时当前消息的长度DataHeaderheader=) dataheader* 消息缓冲器的数据长度为消息长度if(lastpos=header-datalength )//消息缓冲器的剩余未处理数据的长度int nsize=_ lastpos-header-datalengtth //处理网络消息onnetmsg(header ); //将消息缓冲区中的剩余未处理数据转换为memcpy(szmsgbuf,_szMsgBuf header-dataLength,nSize ); //使消息缓冲区的数据末尾位置前进_lastPos=nSize; }else{//消息缓冲区中的其余数据不是完整的消息break返回0; }可运行程序的百度云链接: https://pan.Baidu.com/s/1 D4 vs m2 tgisgua 8to9p5x5w

抽屉代码: fk5m

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。