栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Socket粘包分包解析

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Socket粘包分包解析

一.粘包分包现象(来自Unity 3D网络实战一书)

由于TCP协议本身的机制,客户端与服务器会维持一个连接发送数据,如果发送的网络数据包太小,TCP会等待,然后合并较小的数据包在发送,接收端便无法区分哪些数据是发送端自己分开的,因此便会产生粘包现象,或者接收端把数据放到接受缓冲区中,如果数据没有及时从缓冲区取走,下次取数据时可能出现一次取出多个数据包的情况,如例,客户端发送两次数据,服务器一次接受:

客户端 Send: h e l l o

客户端 Send: u n i t y

服务器 Recv :   h e l l o u n i t y

如果发送的数据包太大,TCP可能会把它拆分成多个包发送,接收端的一次Receive可能只收到一部分数据,如下例,如果发送的字符串较短,可能出现的概率很小.

客户端 Send:h e l l o u n i t y

客户端 Recv: h e l l

服务器 Recv :   l o u n i t y
二.解决方案

处理粘包分包的一种方法是在每个数据包前面加上长度字节(数据包长度,每次接收到数据后,先读取长度字节,如果缓冲区的数据长度大于要提取的字节数,就取出相应字节,否则等待下一次数据接受,如下,客户端要发送”hellounity“ 和”love“两个字符串,它在每个包前面加上一个代表字符串长度的字符,按照TCP机制,接收端收到的字节顺序一定和发送顺序一致(顺序不一致的话tcp在传输控制层会做处理,不会传给上层应用使用,在计算机网络自顶向下一书有说)。

1:假设第一次接收到的是"10hel",那么服务器程序将接受到的数据存入缓冲区,然后读取第一个字节”10“,此时缓冲区长度只有4,服务器不处理,等待下一次接受。

2.假设第二次接收到的是"lounity4l",此时缓冲区便有13个字节,超出第一个包所需要的11个字节(10个数据字节加一个长度字节。于是程序读取缓冲区前11个字节的数据并进行处理,之后缓冲区便只剩下”4l“两个字节。

3…假设第三次接收到的是"ove"三个字节,这时缓冲区便有了 ”4love“ 个5字节,程序读取缓冲区这5个字节并进行处理。

客户端 Send ①:10 h e l l o u n i t y

客户端 Send ②:4 l o v e

服务器 Buffer①:10 h e l

服务器 Buffer ②:  10 h e l l o u n i t y 4 l

服务器 Buffer ③: 4 l o v e


注意:上面都是假设所有字符按照1个字节来的,实际上长度应该是一个int类型(4字节),数据按照协议的字符编码所占字节来计算的。

三.实际项目使用(如果有需求再详细查看文档以及和项目中demo)

1.一般都是定义通信协议

例如:数据长度(4个字节) 数据头

​ 数据(n个字节) 数据体

2.现在java大多都是使用netty框架实现socket通信,netty实现了很多解决粘包分包问题的解决方案,降低用户在实际实现中的复杂度,详细的可以看书

udp没有粘包分包,因为底层使用的是链表结构,一次发送对应一次接受,tcp有,是因为tcp是流,没有边界的,所以需要协议去定义边界。

websocket没有粘包分包是因为底层实现了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/741045.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号