TCP与UDP的区别、TCP的粘包、拆包

TCP和UDP的区别

TCP是一个面向连接的,客户端与服务端、可靠的,基于字节流的传输层协议。双方互相通信之前,T CP需要三次握手建立连接,而UDP没有建立连接的过程。
UDP是一个面向无连接的传输层协议,UDP的数据是基于数据报的。

  • 连接 UDP是无连接的 TCP是面向连接的
  • 可靠 UDP是不可靠传输,不使用流量控制和拥塞控制, TCP是可靠传输,使用流量控制和拥塞控制
  • 连接对象个数 UDP支持一对一、一对多、多对一和多对多交互通信, TCP只能是一对一通信
  • 传输方式 UDP是面向报文,TCP是面向字节流的
  • 首部开销 UDP首部开销小,8字节 , TCP首部开销大,最小20字节,最大60字节

粘包、拆包

假设🈶️2个数据包,没有发生粘包和拆包情况:

粘包:

拆包:

产生TCP粘包和拆包的原因:tcp是以流动的方式传输数据,传输的最小单位为一个报文段(segment)。tcp Header中有个Options标识位,常见的标识为mss(Maximum Segment Size) (TCP数据报中数据部分字节的最大值),连接层每次传输的数据有个最大限制MTU(Maximum Transmission Unit)(数据链路层一个帧的最大值),一般是1500比特,超过这个量要分成多个报文段,mss则是这个最大限制减去TCP的header,光是要传输的数据的大小,一般为1460比特。换算成字节,也就是180多字节。
tcp为提高性能,发送端会将需要发送的数据发送到缓冲区,等待缓冲区满了之后,再将缓冲中的数据发送到接收方。同理,接收方也有缓冲区这样的机制,来接收数据。
原因:

  1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
  2. 应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。(因为要缓冲区满了才进行发送)
  3. 进行mss(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>mss的时候将发生拆包。 (recv到第一片数据是不能去处理业务逻辑的,要判断什么时候recv完整)
  4. 接收方法不及时读取套接字缓冲区数据,这将发生粘包。

解决方案:

  1. 使用带消息头的协议、消息头存储消息开始标识及消息长度信息,服务端获取消息头的时候解析出消息长度,然后向后读取该长度的内容。("可以制定 首部固定多少个字节长度为数据包的长度,不够就补0")
  2. 设置定长消息,服务端每次读取既定长度的内容作为一条完整消息。
  3. 设置消息边界,服务端从网络流中按消息编辑分离出消息内容。 (比如弄个"\n")

linux 下的epoll lt模式下的做法:
1.准备一个4字节变量用于容纳头部数据,另外用一个整形表示头部数据读到第几个字节了(因为有可能一次读不满4字节)
2.读完头部4字节后,就知道长度,开始分配缓冲区,然后从socket读到缓冲区,这里要注意可能eagain,这种情况直接等下一次读消息到来再继续读。
3.直到读满缓冲区就代表数据完整了,然后可以通知上层过来拿数据了。因为我们使用的是lt模式,一次不必读取完socket里的数据,而且这种做法也没有多读数据,不会造成粘包问题

posted @   CrazyShanShan  阅读(361)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示