TCP粘包的缘由 UDP没有粘包

UDP丢包是由于数据包在传送过程当中丢失了 而TCP是基于流式的发送 而且存在丢包重发机制 TCP是可靠链接而UDP是不可靠的这个我就很少说了

关于TCP的粘包 正是因为TCP是流式传送的 也就是链接创建后能够一直不停的发送 并无明确的边界定义 而你用UDP发送的时候 是能够按照一个一个数据包去发送的 一个数据包就是一个明确的边界

而TCP并无数据包的概念 是彻底流式的 他会开辟一个缓冲区 发送端往其中写入数据 每过一段时间就发送出去 而后接收端接收到这些数据 可是并非说我发送了一次数据就确定发送出去了 数据会在缓冲区中 有可能后续发送的数据和以前发送的数据同时存在缓冲区中随后一块儿发送 这就是粘包的一种形式 接收端也有产生粘包的状况 若是应用程序没有及时处理缓冲区中的数据 那么后续到达的数据会继续存放到缓冲区中 也就是2次接收的数据同时存在缓冲区中 下次取缓冲区的时候就会取出2次粘包后的数据 这是粘包的另一种形式 还有其余许多形式 好比填充缓冲区到一半缓冲区满了直接发送了 可是其实那个包还没填充彻底 这个就是不完整的粘包了 剩余数据会在下次发送的时候补上



关于解决方法 若是你是连续的整个数据流 好比发送文件 那么彻底不考虑粘包也无所谓 由于能够创建链接后发送 发送完毕后断开链接 整个数据流就是整个一个文件 不管数据从那里切开都无所谓 整个拼接后依旧是整个一个文件的数据

若是你发送的数据是屡次通讯 好比把一个目录下全部的文件名都发送过去 那么就不能看成一个总体发送了 必须对他们划分边界 有一个很简单的处理方法 就是采用"数据长度+实际数据"的格式来发送数据 这个"数据长度"的格式是固定宽度的 好比4字节 能够表示0~4GB的宽度了 足够用了 这个宽度说明了后续实际数据的宽度 这样你就能够把粘包后的数据按照正确的宽度取出来了

每次都是取出4字节 随后按照正确的宽度取出后续部分的就OK了

若是你的全部数据都是固定宽度的 好比不停的发送温度数据 每一个都是1字节 那么宽度已知了 每次你都取出一个1字节就OK了 因此就不用发送宽度数据了

固然你也能够按照创建链接断开链接来划分边界 每次发送数据都打开关闭一次链接 不过对于频繁的小数据量是不可取的作法 由于开销太大 创建链接和关闭链接也是须要耗费网络流量的

总而言之 粘包的状况是没法绝对避免的 由于网络环境是很复杂的 依赖发送和接收缓冲区的控制是不能保证100%的 只要在发送的数据中说明数据的宽度随后在接收部分按照这个宽度拆开就OK了 宽度全都是统一的已知宽度的状况下拆开更加容易 连在发送端填入宽度数据均可以省去了网络

相关文章
相关标签/搜索