我有两个应用程序在两个不同的服务器上运行。 一个应用程序通过套接字连接连接到另一个应用程序,并通过该套接字发送数据。接收应用程序读取该数据并对其执行某些操作。 发送应用程序使用下一段代码来执行此操作:
out.write(int2ByteArray(size));
out.flush();
Thread.sleep(5);
out.write(full_packet);
out.flush();
full_packet
是一个字节数组,其维度为size * 53
,int2ByteArray()
方法如下所示:
private static byte[] int2ByteArray(int myInt){
return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(myInt).array();
}
基本上,我在发送实际数据之前发送数据包的大小。
接收应用程序使用下一段代码读取数据:
while (running){
long startTime = System.currentTimeMillis();
// read input data
byte[] first_drop = new byte[4];
in.read(first_drop);
int size = byteArray2Int(first_drop);
byte[] packet = new byte [size * packet_size];
Thread.sleep(5);
in.read(packet);
// do some thing with packet
// go to sleep
long endTime = System.currentTimeMillis();
Thread.sleep(1000 - (endTime-startTime));
}
packet_size
等于53. byteArray2Int()
方法如下:
private int byteArray2Int(byte[] bArr){
return ByteBuffer.wrap(bArr).order(ByteOrder.LITTLE_ENDIAN).getInt();
}
in
的类型为DataInputStream
。
问题现在开始了。当我在笔记本电脑上运行这两个应用程序时,一切都很好,所有数据都通过它的发送方式来实现。我运行发送应用程序的几个线程,发送几种大小的数据流。 但是,当在服务器上运行它时,如果数据很大,它就不会按原样运行。 如果我试图发送长度为5300字节的数据包,那么它很好。如果我发送长度为15900字节甚至更大的数据包,在某些时候读取应用程序不能正确读取数据包,并且下次读取大小的4个字节时,它会收到一些奇怪的数字并且它会阻塞应用程序。 当我尝试运行多个线程时会发生同样的事情,每个线程都会发送不同大小的不同数据。
有人能指出这个过程中的问题吗?我该如何解决?有什么建议? 任何帮助将不胜感激。
答案 0 :(得分:0)
InputStream
并不总是读取到达字节数组的所有字节。当数据包足够小时,底层的InputStream
实现可能会返回整个数据包,但是,如果它变大,就像在以后的实验中一样,它可能无法读取它们,因为它的缓冲区不能保持@ycesar提到的大部分数据。一种方法是增加缓冲区大小,但它只是隐藏了问题。要真正解决问题,您需要检查InputStream.read()
的返回值是否与预期的数据包大小相匹配。
在apache commons-io中有一些方便的方法,如IOUtils.read()
。只要遵循许可证,您就可以使用它或根据自己的目的进行修改。它看起来像这样:
public static final int EOF = -1;
public static int read(final InputStream input, final byte[] buffer, final int offset, final int length)
throws IOException {
if (length < 0) {
throw new IllegalArgumentException("Length must not be negative: " + length);
}
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
final int count = input.read(buffer, offset + location, remaining);
if (EOF == count) { // EOF
break;
}
remaining -= count;
}
return length - remaining;
}
以上代码是从https://github.com/apache/commons-io/blob/2.5/src/main/java/org/apache/commons/io/IOUtils.java#L2901下获得许可的Apache 2.0复制而来的。没有修改。
答案 1 :(得分:0)
您忽略read()
返回的计数。实现这一目标的最简单方法是DataInputStream.readFully()
。
答案 2 :(得分:-1)
我不确定但是默认套接字接收缓冲可能低于预期。为什么不尝试使用setReceiveBufferSize()
函数来增加此接收缓冲区大小?
希望它对你有所帮助。