我尝试在服务器端接收原始二进制数据包。我控制数据格式并指定数据包的前4个字节来描述数据包的长度(它是转换为byte []和返回的int值)。这非常有效,我得到了正确的数字(我也可以监控并检查客户端)。这是代码:
is = connectionSocket.getInputStream();
byte[] intArray = new byte[4];
//read the 4-byte int value to array
is.read(intArray, 0, 4);
int packetLength = ByteBuffer.wrap(intArray).getInt();
然后我想将包(不包括length-header)读取到自定义字节数组:
byte[] packet = new byte[packetLength];//make a buffer ready
is.read(packet, 0, packetLength);//read the whole packet to array
如果发送的byte []的长度为1444或更短,则一切正常。但超出此限制的数据包将无法正常接收。数据包阵列将在开头正确填充数据,但在限制之后,只有零,直到结束这样
Positon: ...|1440|1441|1442|1443|1444|1445|1446|1447|.........|packetLength-1
Data: ...| 59 |-73 | 125| -3 | 0 | 0 | 0 | 0 |..zeros..| 0
从我作为一个13岁的崇拜者 - 互联网调整大师的日子我还记得,在Windows机器上有一个大约1500字节的标准MTU(最大传输单位)。事实上,我的接收网络适配器的MTU为1500.这可疑地接近1444,所以我增加了MTU,但遗憾的是没有结果。 Java不应该用这种低级别的东西来打扰我,但也许这不是巧合。顺便说一句,客户端是Android智能手机,接收器是Windows 7机器。
是否有人有其他想法或更好的解决方案?
答案 0 :(得分:1)
您忽略了read(),
返回的计数,并假设它填充了缓冲区。没有义务这样做。见Javadoc。
正确地执行您正在执行的操作的简单方法是使用DataInputStream.readInt(),
,然后使用readFully().
NB与您的评论相反,当然,仅添加int size =
根本没有效果。这是不可能的。由于其他原因,时间发生了变化,因此真正到达了四个字节。
答案 1 :(得分:-1)
最后,我发现了自己阅读的种族条件性质,但感谢您的帮助和澄清。当我观察到设置调试停止解决问题时,我注意到了这一点,这给了缓冲区时间来完成它们的工作。使用DataInputStream也可以更好地编写代码,再次感谢。这是我的(希望)最终解决方案:
DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());
int packetLength = dis.readInt();
byte[] packet = new byte[packetLength];//make a buffer ready
dis.readFully(packet);//read full packet to buffer