套接字间歇性地只读取1448/2896个字节

时间:2018-04-10 11:37:09

标签: java sockets datainputstream apache-commons-io

我正在使用Commons-IO从Socket读取和写入。事情一直有效,直到有效载荷大小为1448/2896最大

以下是代码段。真的不确定如何处理它。 检查系统缓冲区大小

$ cat /proc/sys/net/ipv4/tcp_wmem
4096    16384   4194304
public static void usingCommonsIO(){
    Socket socket = null;
    try {
        socket = new Socket(serverIP, 55000);
        IOUtils.write(request.getBytes(), socket.getOutputStream());
        System.out.println("Message Sent....");
        StringBuilder response = new StringBuilder();
        String resp =IOUtils.toString(socket.getInputStream(), "UTF-8");
        System.out.println(resp);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

或者尝试使用DataInputStream但没有运气。代码剪辑如下。

public static void usingDataIOStream(String requestStr){
    Socket socket = null;
    try {
        socket = new Socket("192.168.1.6", 55000);
        System.out.println("Request Length -:" + request.length());
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        out.write(requestStr.getBytes("UTF-8"), 0, requestStr.length());
        out.flush();
        System.out.println("Message Sent....");
        DataInputStream din = new DataInputStream(socket.getInputStream());
        byte[] response = new byte[16*1024];
        int responseLength = din.read(response);
        System.out.println("Response -:" + new java.lang.String(response, 0, responseLength));

    } catch (IOException e) {
        e.printStackTrace();
    }

}

令人困惑的部分是,相同的代码有时仅使用1448字节,有时最多只能处理2896字节。没有具体的模式。

更新1

要模拟它,尝试自己编写Server套接字,代码如下。注意到这一点的奇怪之处是,在第一次请求时,读取并正确接收了大小为6500的有效载荷。连接重置从第二个请求开始。我在这里错过了什么吗?

public static void usingBAOS() throws IOException {

    server = new ServerSocket(port);
    Socket socket = null;
    DataInputStream din = null;
    DataOutputStream dos = null;
    while (true) {
        System.out.println("Waiting  for Client...");
        try {
            // Accepting Client's connection
            socket = server.accept();
            System.out.println("Connnected to client " + socket.getInetAddress());
            din = new DataInputStream(socket.getInputStream());
            // Read request payload from Socket
            String requestString = readRequest(din);
            System.out.println("Request Read.....");
            System.out.println("Writing Response.....");
            // Writing response to socket
            dos = writeResponse(socket, requestString);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //close resources
            din.close();
            System.out.println("InputStream is closed......");
            dos.close();
            System.out.println("OutputStream is closed......");
            socket.close();
            System.out.println("Socket is closed......");
        }
    }
}

private static DataOutputStream writeResponse(Socket socket, String requestString) throws IOException {
    String responseString = "Hi Client" + requestString;

    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
    //write object to Socket
    dos.write(responseString.getBytes(),0, responseString.getBytes().length);
    dos.flush();
    return dos;
}

private static String readRequest(DataInputStream din) throws IOException {
    byte[] response = new byte[16*1024];
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int n = 0;
    boolean read = true;
    while(read){
        n = din.read(response);
        baos.write(response, 0, n);
        if(baos.toString().length() == n){
            read = false;
        }
    }
    baos.flush();
    String requestString = baos.toString();
    return requestString;
}

1 个答案:

答案 0 :(得分:0)

尽管在编写此答案时这个问题已经过时,但我还是将其放在此处,以备其他人解决。在Android 8.0设备上使用缓冲的数据输入和输出流时,我天真地认为这样做会遇到相同的问题:

int len = 2304;
byte[] data = new byte[len];
inputStream.read(data, 0, len);

将读取我通过套接字发送的所有数据。但是,正如@Kayaman在评论中所建议的那样,即使有可用的字节,也不能保证实际上从缓冲区读取了len个字节的数据。实际上,它在documentation中:

  

public final int read(byte[] b, int off, int len) throws IOException

     

从包含的输入流中读取多达len个字节的数据到一个字节数组中。尝试读取多达len个字节,但可能读取的字节数较小,可能为零。实际读取的字节数以整数形式返回。

实际上,如果它不能读取所有数据,那么唯一的判断方法就是捕获返回的值。然后,我的解决方案是监视实际从流中读取的字节数,并在循环中仅调用read(),如下所示:

int i = 0;
len = 2304;
byte[] data = new byte[len];
while (i < len)
{
    i += socket.inputStream.read(data, i, len - i);
}

希望这对某人有帮助。