Socket TCP协议 实时通信的粘包处理 Java与C++实现

原理:

(经典)tcp粘包分析

场景:

此项目是处理实时监测数据,一旦tcp socket建立连接,会不间断实时发送数据,峰值输数据量在3M/秒,这样的数据量必然会造成数据粘包。

目的:

TCP连接面向流,读取网络的一包数据不一定正好是协议里定义的完整的一包,有可能是多包,有可能是半包,也有可能是一包半,现在要将每次读取的数据进行分包,也就是粘包处理,提取出完整的一包数据供上层使用,上层需要将完整的一包数据里的数据根据协议定义的格式提取出来。

实现:

将收到的数据copy到缓存区,在缓存区里循环从起始位按照协议找出完整的一包数据提取出来。
关键点在于根据协议找出完整一包数据的长度

  1. 从网络读取数据后拷贝到缓存区
  2. 判断:缓存区里数据占位,长度小于某个值n,return再次读取网络数据。这个值n长度的数据内要能解析出单个完整包的长度,以便后续处理
  3. 循环:如果缓存区长度大于解析出来的完整一包的长度
  4. 执行: 取出完整一包数据后,然后剔除这包,将缓存区剩余数据放置起始位
  5. 循环里再次判断: 长度小于某个值n,return再次读取网络数据。 这个值n长度的数据内要能解析出单个完整包的长度,以便后续处理

如果协议定义了帧头,可以在取包的长度之前校验帧头,确保数据正确。

这里说明定义缓冲区buffer的长度大小:必须要大于可能收到的最大数据包的长度加上read读取一次网络最大数据长度
原因是缓冲区里可能剩下不到一包数据,下一次读取网络数据后要将数据copy至缓冲区,如果超过缓冲区大小就无法进行处理。可在copy时加一层判断,如果超过缓存区,就直接返回,断开连接。代表这种数据包不能进行处理。如果缓存区设计合理,不会出现此种情况。read读取一次网络最大数据长度是在read到的buffer定义的长度。缓冲区的buffer不要设置过大,占用太多内存。
数据源

数据源说明:第一位固定#。第二位表示之后有几位代表了之后的数据的长度,比如第一条数据的第二位4,代表之后的四位3350是从0:开始共有3350个字节长度的数据。之后的数据跟业务相关。

主要代码:

Java实现:
不可用于生产环境,理解思想后根据业务数据处理粘包

private static int MAXDATALEN = 500000; //处理数据缓冲池的长度
private static int RECEIVEDATALEN = 200000
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值