粘包拆包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输层都有可能发生。咱们平常的网络应用开发大都在传输层进行,因为UDP有消息保护边界,不会发生粘包拆包问题,所以粘包拆包问题只发生在TCP协议中。html
假设客户端向服务端连续发送了两个数据包,用packet1和packet2来表示,那么服务端收到的数据能够分为三种,现列举以下:服务器
**第一种状况:**接收端正常收到两个数据包,即没有发生拆包和粘包的现象,此种状况不在本文的讨论范围内。微信
**第二种状况:**接收端只收到一个数据包,因为TCP是不会出现丢包的,因此这一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包。这种状况因为接收端不知道这两个数据包的界限,因此对于接收端来讲很难处理。网络
**第三种状况:**这种状况有两种表现形式,以下图。接收端收到了两个数据包,可是这两个数据包要么是不完整的,要么就是多出来一块,这种状况即发生了拆包和粘包。这两种状况若是不加特殊处理,对于接收端一样是很差处理的。ui
发生TCP粘包、拆包主要是因为下面一些缘由:cdn
应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。htm
应用程序写入数据小于套接字缓冲区大小,网卡将应用屡次写入的数据发送到网络上,这将会发生粘包。blog
进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。开发
接收方法不及时读取套接字缓冲区数据,这将发生粘包。get
TCP自己是面向流的,做为网络服务器,如何从这源源不断涌来的数据流中拆分出或者合并出有意义的信息呢?一般会有如下一些经常使用的方法:
一、发送端给每一个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,经过读取包首部的长度字段,便知道每个数据包的实际长度了。
二、发送端将每一个数据包封装为固定长度(不够的能够经过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就天然而然的把每一个数据包拆分开来。
三、能够在数据包之间设置边界,如添加特殊符号,这样,接收端经过这个边界就能够将不一样的数据包拆分开。
若是你们喜欢个人文章,能够关注我的订阅号。欢迎随时留言、交流。若是想加入微信群的话一块儿讨论的话,请加管理员简栈文化-小助手(lastpass4u),他会拉大家进群。