Socket中粘包的坑的处理
来源:互联网 发布:淘宝评价怎么修改好评 编辑:程序博客网 时间:2024/06/06 03:05
经常在网上看到很多类似于粘包的问题以及处理,但是因为这个跟自己本身的工作内容关系不大,所以也就没怎么了解。结果今天就被坑了一大把。
起因
最近由于有个投屏的软件需要模拟多个客户端进行连接投屏,所以用java写了个客户端模拟多个同时进行并发同屏的情况。而他的协议过程是这样子的。当你发送开始投屏的命令一样,接收端也就是我们所说的服务端会回复几条socket的信息(这个是重点),但是因为我们是模拟客户端的,所以并不是所有的数据都是我关心的。只有其中一条关于回复的端口的信息是需要接收处理。所以就有了坑的问题了。
问题
在测试的过程中发现,经常是有概率的出现模拟了4个客户端进行并发时服务端只回复了3条关于端口的数据,总会有概率的少了一两条。那问题总得定位到底是代码处理的问题,还是说是机器本身就没有收到对应的包呢。
以下是wireshark抓包的结果
实际证明是有收到这个回复包的, 那么就证明确实是代码的问题了。那代码问题在哪 我们看看出错的代码
byte len[] = new byte[1024]; int count = socket.getInputStream().read(len); byte[] temp = new byte[count]; for (int i = 0; i < count; i++) { temp[i] = len[i]; } ... if (temp[9] == 1) { switch (temp[10]) { case 101: Msg.CMsgConnectResp cMsgConnectResp = Msg.CMsgConnectResp.parseFrom(msg); log.append("收到指令类型:" + (temp[9]) + ", 指令号:" + temp[10] + "连接结果:" + cMsgConnectResp.getResultType() + ", 接收端版本:" + cMsgConnectResp.getReceiverVersion() + ", 支持最大窗口数量:" + cMsgConnectResp.getMaxWindowCount() + "\n");....
代码实际很简单就是声明一个byte的数组,每次读1024个字节。再来将读取到的数据进行解析,表面上看起来没什么问题。
可是细想一个问题。就是刚才我们提到的,当我们进行投屏的时候,服务端是会连续回复几个socket的数据的,然而我们一下子读了那么1024个字节的数据,就会把几个数据包都读到一起,那如果幸运的话,回复端口的数据先到了,嗯 没问题,那如果是其他数据类型先到了,会发生什么事情呢。。很悲剧。数据包会被丢弃掉。
解决
既然遇到这个问题,就肯定有解决的方法。下来看看解决的方式
byte len[] = new byte[11]; socket.getInputStream().read(len); byte[] msgLenArray = new byte[4]; System.arraycopy(len, 0, msgLenArray, 0, 4); int msgLen = (MsgUtils.bytesToInt2(msgLenArray)); if (msgLen > 0) { byte contentByte[] = new byte[msgLen]; socket.getInputStream().read(contentByte); System.out.println(len[9]); System.out.println(len[10]); if (len[9] == 1) { }
以上就能够完美的解决问题了,我们每次读取都读11个字节。因为协议头的长度就是11个字节。再来根据协议头里面的body的长度我们再去读对应的长度。这样子就避免了读取的时候盲目的读取1024个长度的问题了。
- Socket中粘包的坑的处理
- Socket的安全策略处理
- socket的处理的注意事项
- socket中so_error的处理
- Socket分包处理的解决方案
- (java)处理socket通信过程中粘包的情况
- reamld中socket的处理方式
- socket中网络字节序的处理
- C# Socket的粘包处理
- Socket bind failed: [730048]异常的处理
- 接收socket数据的粘包处理
- socket中的函数遇见EINTR的处理
- Socket粘包问题的处理
- socket中的函数遇见EINTR的处理
- socket中的函数遇见EINTR的处理
- socket中的函数遇见EINTR的处理
- socket中的函数遇见EINTR的处理
- socket中的函数遇见EINTR的处理
- 列车售票的可线性化编程-Java
- C语言——数组与指针进阶(二)
- linux部署服务器遇到的问题(四)
- RadioButton和CheckBox用法及监听
- 消息队列activemq整合spring发送端和接收端配置
- Socket中粘包的坑的处理
- 51nod 1169 石子游戏
- Linux下部署多个Tomcat端
- mysql数据库常用命令
- WEBVX辅助小程序。纯协议
- Laravel4中使用的验证
- java集合继承关系
- 手机meta标签(让心灵去旅行)
- Compass