产生tcp粘包和拆包的原因
我们知道tcp是以流动的方式传输数据,传输的最小单位为一个报文段(segment)。tcp Header中有个Options标识位,常见的标识为mss(Maximum Segment Size最大消息长度)指的是,连接层每次传输的数据有个最大限制MTU(Maximum Transmission Unit),一般是1500比特,超过这个量要分成多个报文段,mss则是这个最大限制减去TCP的header,光是要传输的数据的大小,一般为1460比特。换算成字节,也就是180多字节。
MSS = MTU - header
tcp为提高性能,发送端会将需要发送的数据发送到缓冲区,等待缓冲区满了之后,再将缓冲中的数据发送到接收方。同理,接收方也有缓冲区这样的机制,来接收数据。
发生TCP粘包、拆包主要是由于下面一些原因:
应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。
进行mss(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>mss的时候将发生拆包。
接收方法不及时读取套接字缓冲区数据,这将发生粘包。
……
如何解决拆包粘包
既然知道了tcp是无界的数据流,且协议本身无法避免粘包,拆包的发生,那我们只能在应用层数据协议上,加以控制。通常在制定传输数据时,可以使用如下方法:
1、使用带消息头的协议、消息头存储消息开始标识及消息长度信息,服务端获取消息头的时候解析出消息长度,然后向后读取该长度的内容。
2、设置定长消息,服务端每次读取既定长度的内容作为一条完整消息。
3、设置消息边界,服务端从网络流中按消息编辑分离出消息内容。
=====================================================================
问题:
TCP是以段为单位进行数据包的发送的。
(1)在建立TCP连接的同时,也可以确定发送数据包的单位,称之为“最大消息长度”:MSS。最理想的情况是,最大消息长度MSS正好是IP层中不被分片处理的最大数据长度。
(2)TCP在传送大量数据的时候,是以“段=MSS的大小”将数据进行分割发送的,进行重发时也是以MSS为单位的。
(3)最大消息长度——MSS是在三次握手的时候,在两端主机之间被计算得出的。两端主机在发出“建立TCP连接请求的SYN包”时,会在SYN包的TCP首部中写入MSS选项,告诉对方自己所能够适应的MSS的大小,然后发送端主机会在两者之间选择一个较小的MSS值投入使用。
TCP为什么引入接受缓存这个数据结构?
如果没有接受缓存的话,或者说只有一个缓存的话,为了保证接受的数据是按顺序传输的,所以如果位于x序号之后的序号分组先到达目的主机的运输层的话必然丢弃,这样的话将在重传上花费很大的开销,所以一般如果有过大的序号达到接收端,那么会按照序号缓存起来等待之前的序号分许到达,然后一并交付到应用进程。
TCP 粘包/拆包的原因及解决方法
TCP是以流的方式来处理数据,一个完整的包可能会被TCP拆分成多个包进行发送,也可能把小的封装成一个大的数据包发送。
TCP粘包/分包的原因:
应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,而应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包现象;
进行MSS大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包
以太网帧的payload(净荷)大于MTU(1500字节)进行ip分片。
解决方法
消息定长:FixedLengthFrameDecoder类
包尾增加特殊字符分割:行分隔符类:LineBasedFrameDecoder或自定义分隔符类 :DelimiterBasedFrameDecoder
将消息分为消息头和消息体:LengthFieldBasedFrameDecoder类。分为有头部的拆包与粘包、长度字段在前且有头部的拆包与粘包、多扩展头部的拆包与粘包。
相关推荐
主要介绍了使用Netty解决TCP粘包和拆包问题过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
发生TCP粘包或拆包有很多原因,现列出常见的几点,可能不全面,欢迎补充, 1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。 2、待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。 3、...
本demo模拟了TCP通信中发送端和接收端的行为,并利用序列化和反序列化的思想,自定义协议来解决TCP的粘包和拆包问题。
tcp 粘包 拆包解决思路以代码,提供DEMO,采用 包长+内容缓冲区 组织方法,未采用分隔符以及定长包,因为我觉得包长+内容缓冲区比较灵活
【游戏开发】网络编程之浅谈TCP粘包、拆包问题及其解决方案.docx
主要给大家介绍了Golang TCP粘包拆包问题的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Golang具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
通过socket通讯实现服务器与客户端的连接。首先服务器利用udp广播发送自己的ip地址,客户端在收到广播后通过此ip以tcp连接的方式连接服务器来通讯。
面试题:聊聊TCP的粘包、拆包以及解决方案.docx
Netty中粘包和拆包的解决方案.docx
粘包和拆包及Netty解决方案.docx
主要为大家详细介绍了C#中TCP粘包问题的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本程序使用设计良好的函数,使得应用层不需要考虑网络消息是如何被接受和发送的,重点演示了如何优雅地处理TCP/IP网络数据粘包和丢包的刺手问题,你只要调用相应的函数就可以了。你只需要定义自己的协议头和消息...
c++服务器 拆包粘包 过程 千万别问我是基于TCP的还是UDP的...
Netty粘包与拆包源码
什么是粘包拆包,为什么发生拆包粘包问题,如何处理拆包粘包问题
Netty粘包-拆包应用案例及解决方案分析.docx
易语言TCP粘包拆包组包应用之协议长度方式与标志符方式。@流云思水。
Socket编程TCP粘包问题及解决方案.docx
Netty粘包拆包解决方案.docx