读取inputstream时出错:java服务器中的软件导致连接中止

时间:2018-07-27 19:00:04

标签: java android sockets inputstream serversocket

我基本上是想在Android设备上托管服务器。客户端设备通过TCP连接到服务器并发送请求。服务器执行客户端请求的操作,然后将数据写回到套接字。服务器不会终止连接,并且请求将通过套接字连续读取并回复。

注意:每个请求消息的前4个字节包含实际消息/请求的长度。

parseXmlInputAndExecuteCmd函数根据输入XML字符串的内容执行各种异步操作。最终,这会导致'allowResponse'变量的布尔值更改为true,并生成确定的响应,该响应存储在String类型的变量中,称为'response'。布尔值“ allowResponse”变为true后,线程将恢复执行并将响应写回到套接字的OutputStream

其中一些异步操作包括与公司VPN的连接和断开连接。这可能是错误的原因吗?

一些正在使用的类级别变量是:

private volatile boolean allowResponse = false;
private String response;

服务器代码:

    private void startServer() {
    try {
        ServerSocket serverSocket = new ServerSocket(8080);
        while (true) {
            Socket connectionSocket = serverSocket.accept();
            BufferedInputStream bufInpStream = new BufferedInputStream(connectionSocket.getInputStream());
            BufferedOutputStream bufOutStream = new BufferedOutputStream(connectionSocket.getOutputStream());
            ByteArrayOutputStream contentLengthBaos = new ByteArrayOutputStream();
            int c;
            int count = 0;
            while ((c = bufInpStream.read()) != -1) {
                contentLengthBaos.write(c);
                count++;
                if (count == 4) {
                    int contLen = getMessageLength(contentLengthBaos);
                    String content = getMessageContent(bufInpStream, contLen);
                    parseXmlInputAndExecuteCmd(content);
                    count = 0;
                    while (!allowResponse) {
                        Thread.sleep(1000);
                    }
                    allowResponse = false;
                    byte[] responseDataBytes = response.getBytes();
                    int outputContLen = responseDataBytes.length;
                    byte[] contLengthBytes = ByteBuffer.allocate(4).putInt(outputContLen).array();
                    ByteArrayOutputStream o = new ByteArrayOutputStream();
                    o.write(contLengthBytes);
                    o.write(responseDataBytes);
                    byte finalOutPutBytes[] = o.toByteArray();
                    bufOutStream.write(finalOutPutBytes);
                    bufOutStream.flush();
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@NonNull
private String getMessageContent(BufferedInputStream inFromClient, int contLen) throws IOException {
    ByteArrayOutputStream contentBaos = new ByteArrayOutputStream();
    byte[] contentBytes = new byte[contLen];
    for (int i = 0; i < contLen; i++) {
        contentBaos.write(inFromClient.read());
        ByteArrayInputStream bais = new ByteArrayInputStream(contentBaos.toByteArray());
        bais.read(contentBytes);
    }
    String content = new String(contentBytes);
    Log.d(TAG, "Content : " + content);
    return content;
}

private int getMessageLength(ByteArrayOutputStream contentLengthBaos) {
    byte[] firstFourBytesArr = contentLengthBaos.toByteArray();
    int contLen = new BigInteger(firstFourBytesArr).intValue();
    contentLengthBaos = new ByteArrayOutputStream();
    Log.d(TAG, "Content length: " + contLen);
    return contLen;
}

使用以下代码行启动服务器:

Thread serverThread = new Thread(new Runnable() {
        @Override
        public void run() {
            startServer();
        }
    });
    serverThread.start();

我正在获取以下错误堆栈跟踪:

W/System.err: java.net.SocketException: Software caused connection abort
                  at java.net.SocketInputStream.socketRead0(Native Method)
                  at java.net.SocketInputStream.socketRead(SocketInputStream.java:114)
W/System.err:     at java.net.SocketInputStream.read(SocketInputStream.java:170)
W/System.err:     at java.net.SocketInputStream.read(SocketInputStream.java:139)
W/System.err:     at java.io.BufferedInputStream.fill(BufferedInputStream.java:248)
W/System.err:     at java.io.BufferedInputStream.read(BufferedInputStream.java:267)
                  at com.example.umathur.myapplication.MainActivity.startServer(MainActivity.java:192)
                  at com.example.umathur.myapplication.MainActivity.access$000(MainActivity.java:61)
                  at com.example.umathur.myapplication.MainActivity$1.run(MainActivity.java:139)
                  at java.lang.Thread.run(Thread.java:764)

我收到一个错误消息:java.net.SocketException: Software caused connection abort

我不确定在输入流/输出流的使用中哪里出了问题。我在下面的行(stacktrace中提到的行号192)处得到错误:

while ((c = inputStream.read()) != -1)

在关于StackOverflow的一些类似问题中,我看到人们指出这可能是公司防火墙配置问题?那是对的吗 ?如果是这样,我该如何解决?

这可能是客户端代码(我无权访问)书写不正确的问题吗?

2 个答案:

答案 0 :(得分:1)

我无法在本地重现您的问题,并且有一些情况告诉我您的触发条件非常具体,但是这里有一些方法可以尝试帮助您诊断和解决问题。

  1. 您的代码: :如果是您的代码,则现有的Web服务器代码应该可以使用。尝试使用此nice minimal Medium article on how to create your own Java web server中的代码中的代码。
  2. 防火墙: :如果是防火墙,请与您的网络管理员/团队等联系。如果您不知道它是谁,请以高调发言您公司中的一个您很愿意问的人,他们应该能够将您导向合适的人。
  3. 套接字SO_KEEPALIVE选项: :我找到了一个interesting SuperUser question on the subject,并在您的套接字上看到了此问题may be caused by the fact that you don't have the SO_KEEPALIVE flag set。答案是关于PuTTY的,但是我认为尝试使用Java套接字可能是值得的。当然,这是要尝试的低挂水果。因此,请尝试在connectionSocket.setKeepAlive(true);行之后通过调用Socket connectionSocket = serverSocket.accept();进行添加。

答案 1 :(得分:0)

我试图在我的PC中运行您的代码(而不是在Android中),并且通过从浏览器到localhost:8080的简单调用就可以很好地工作。

我认为您可以在设备内部执行同样的操作,只是想知道这是否是客户端问题。

我编辑了这两行以避免长时间等待:

byte[] contentBytes = new byte[10];
    for (int i = 0; i < 10; i++) {