发送端可以是一 K 一 K 地发送数据, 而接收端的应用程序可以两 K 两 K 地提走数据, 当然也有可能一次提走 3K 或 6K 数据, 或者一次只提走几个字节的数据, 也就是说, 应用程序所看到的数据是一个整体, 或说是一个流(stream), 一条消息有多少字节对应用程序是不可见的, 因此 TCP 协议是面向流的协议, 这也是容易出现粘包问题的原因.
粘包问题主要还是因为接收方不知道消息之间的界限, 不知道一次性提取多少字节的数据所造成的.
发送方引起的粘包是由 TCP 协议本身造成的, TCP 为提高传输效率, 发送方往往要收集到足够多的数据后才发送一个 TCP 段. 若连续几次需要 send 的数据都很少, 通常 TCP 会根据优化算法把这些数据合成一个 TCP 段后一次发送出去, 这样接收方就收到了粘包数据.
TCP(transport control protocol, 传输控制协议)是面向连接的, 面向流的, 提供高可靠性服务. 收发两端 (客户端和服务器端) 都要有一一成对的 socket, 因此, 发送端为了将多个发往接收端的包, 更有效的发到对方, 使用了优化方法(Nagle 算法), 将多次间隔较小且数据量小的数据, 合并成一个大的数据块, 然后进行封包. 这样, 接收端, 就难于分辨出来了, 必须提供科学的拆包机制. 即面向流的通信是无消息保护边界的.
UDP(user datagram protocol, 用户数据报协议)是无连接的, 面向消息的, 提供高效率服务. 不会使用块的合并优化算法,, 由于 UDP 支持的是一对多的模式, 所以接收端的 skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的 UDP 包, 在每个 UDP 包中就有了消息头(消息来源地址, 端口等信息), 这样, 对于接收端来说, 就容易进行区分处理了. 即面向消息的通信是有消息保护边界的.
tcp 是基于数据流的, 于是收发的消息不能为空, 这就需要在客户端和服务端都添加空消息的处理机制, 防止程序卡住, 而 udp 是基于数据报的, 即便是你输入的是空内容(直接回车), 那也不是空消息, udp 协议会帮你封装上消息头
发生粘包的情况
1, 发送端需要等缓冲区满才发送出去, 造成粘包(发送数据时间间隔很短, 数据了很小, 会合到一起, 产生粘包)
2, 接收方不及时接收缓冲区的包, 造成多个包接收(客户端发送了一段数据, 服务端只收了一小部分, 服务端下次再收的时候还是从缓冲区拿上次遗留的数据, 产生粘包)
cp 是可靠传输, udp 是不可靠传输:
tcp 在数据传输时, 发送端先把数据发送到自己的缓存中, 然后协议控制将缓存中的数据发往对端, 对端返回一个 ack=1, 发送端则清理缓存中的数据, 对端返回 ack=0, 则重新发送数据, 所以 tcp 是可靠的
而 udp 发送数据, 对端是不会返回确认信息的, 因此不可靠
来源: http://www.bubuko.com/infodetail-2960645.html