Java 从套接字读取的字节数组不一致

Java 从套接字读取的字节数组不一致,java,multithreading,sockets,network-programming,Java,Multithreading,Sockets,Network Programming,我有两个应用程序在两个不同的服务器上运行。 一个应用程序通过套接字连接到另一个应用程序,并通过该套接字发送数据。接收应用程序读取该数据并对其进行处理。 发送应用程序使用下一段代码执行此操作: out.write(int2ByteArray(size)); out.flush(); Thread.sleep(5); out.write(full_packet); out.flush(); full_packet是一个字节数组,其维度为size*53和int2ByteArray()方法如下所示:

我有两个应用程序在两个不同的服务器上运行。 一个应用程序通过套接字连接到另一个应用程序,并通过该套接字发送数据。接收应用程序读取该数据并对其进行处理。 发送应用程序使用下一段代码执行此操作:

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));
 }
数据包大小
等于53
byteArray2Int()
方法如下所示:

private int byteArray2Int(byte[] bArr){
        return ByteBuffer.wrap(bArr).order(ByteOrder.LITTLE_ENDIAN).getInt();
    }
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;
}
中的
类型为
DataInputStream

问题从现在开始。当我在笔记本电脑上运行这两个应用程序时,一切都很好,所有数据都是通过发送的方式发送的。我运行发送应用程序的几个线程,发送几种大小的数据流。 然而,当在服务器上运行时,如果数据太大,它就不会像应该的那样通过。 如果我试图发送5300字节长的数据包,那么就可以了。如果我发送的数据包长度为15900字节,甚至更大,那么在某个时候,读取应用程序无法正确读取数据包,下次读取4字节大小的数据包时,它会收到一些奇怪的数字,从而阻塞应用程序。 当我尝试运行多个线程时,也会发生同样的情况,每个线程发送不同大小的数据

有人能指出这个过程中的问题吗?我怎样才能修好它?有什么建议吗?
任何帮助都将不胜感激。

InputStream
并不总是读取到达字节数组的所有字节。当数据包足够小时,底层的
InputStream
实现可能会返回整个数据包,但是,如果数据包变大,如您稍后的实验所示,它可能无法读取整个数据包,因为它的缓冲区无法容纳@ycesar提到的那么多数据。一种方法是增加缓冲区大小,但它只是隐藏了问题。要真正解决这个问题,您需要检查
InputStream.read()
的返回值是否与预期的数据包大小匹配

ApacheCommons io中有一些方便的方法,如
IOUtils.read()
。只要遵守许可证,您可以出于自己的目的使用或修改它。看起来是这样的:

private int byteArray2Int(byte[] bArr){
        return ByteBuffer.wrap(bArr).order(ByteOrder.LITTLE_ENDIAN).getInt();
    }
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;
}
publicstaticfinal int-EOF=-1;
公共静态整型读取(最终InputStream输入,最终字节[]缓冲区,最终整型偏移量,最终整型长度)
抛出IOException{
如果(长度<0){
抛出新的IllegalArgumentException(“长度不能为负:“+Length”);
}
int剩余=长度;
而(剩余>0){
最终整数位置=长度-剩余;
最终整数计数=输入.读取(缓冲区,偏移量+位置,剩余);
如果(EOF==计数){//EOF
打破
}
剩余-=计数;
}
返回长度-剩余长度;
}

上述代码是从许可证下复制的。没有修改。

我不确定,但可能默认套接字接收bufer低于预期。为什么不尝试使用
setReceiveBufferSize()
函数来增加此接收缓冲区的大小


希望它能帮助您。

您忽略了
read()
返回的计数。实现这一点的最简单方法是使用
DataInputStream.readFully()

无法保证
out.flush()
调用确实通过网络发送数据包。看看为什么小包可以拿着。正如@glee8e的回答所暗示的,TCP流就是那个流。您不能依赖于数据包边界的保留。这只是隐藏了实际问题,并且接收缓冲区的大小不打算这样使用。它是为了确保快速下载,而不是解决这样的问题。这里没有证据表明套接字接收缓冲区太小,而且您还没有确定真正的问题。@EJP对不起,但是如何解决过早的EOF?我搜索了这么多,但他没有解释为什么他的代码有效。以前我只使用http客户端库,甚至从来没有手动使用过HttpURLConnections。现在您已经发布了EOF变量的值,并且清楚地表明它是一个值为-1的常量,如果EOF过早出现,此代码不会失败。:/似乎我甚至不适合复制。