Java写入已关闭的输出流不会抛出IOException异常。

6

以下是我的客户端/服务器流程:

在主线程中创建Socket。

  1. 将Socket传递给线程1。
  2. 客户端向服务器发送数据。
  3. 服务器响应客户端。
  4. 服务器通过调用close()关闭输入流、输出流和套接字。
  5. Socket返回到主线程,然后传递给线程2。
  6. 客户端向服务器写入数据-没有异常、没有错误,服务器没有收到任何数据。
  7. 客户端尝试读取数据-没有异常、没有错误。

如何检测套接字已关闭的问题?

try {
        os = new DataOutputStream(this.socket.getOutputStream());
        os.write(data);
        os.flush();
        System.out.println("Written " + data.length + " bytes");
    } catch (IOException e) {
        System.out.println("Client failed to write to stream");
        System.out.println(e.getMessage());
        e.printStackTrace();
    }

异常从未被抛出。它显示“已写入60个字节”。有什么想法吗?


更新

这是我读取响应的方式。等待数据,读取前4个字节(这给出响应的长度),并继续读取,直到读取指定长度。由于没有数据进来,此循环永远不会结束。

is = new DataInputStream(this.socket.getInputStream());
    while(true){
        while(is.available() > 0){
            bos.write(is.read());
        }
        if(contentLength == 0 && bos.size() > 3){
            byte[] bytes = bos.toByteArray();
            byte[] size = Arrays.copyOf(bytes, 4);
            contentLength = ByteBuffer.wrap(size).getInt();
        }
        if(bos.size() - 4 < contentLength){
            continue;
        }
        break;
    }

你有检查 SocketException 吗?如果你关闭了所有的东西,那么它也应该抛出异常。 - Rishal
是的,没有抛出异常。我更新了问题,并提供了有关在线程之间传递套接字的附加信息。 - user2914191
1
一个关闭的流可以读取多少字节而不会阻塞?没有。因此 available() 必须返回零。 - erickson
你并不是在写入一个已关闭的输出流,而是在写入一个可能已被对等方关闭的连接。这两者并不相同。 - user207421
2个回答

2
当服务器关闭TCP连接的一端时,它会发送一个FIN数据包告诉客户端。客户端程序将其视为InputStream到达结尾。此外,如果客户端尝试写入,服务器将发送RST数据包以表示错误。如果客户端程序在收到RST后尝试写入,则API将抛出带有消息“connection reset”的SocketException异常。
你在这里需要检测输入的结尾。
    while(is.available() > 0){
        bos.write(is.read());
    }

available 方法可能不是你所想象的那样。如果你想读取4个字节,那就读取4个字节:

byte[] bytes = new byte[4];
is.readFully(bytes); // throws EOFException on end of input

1
它说它写了60个字节,因为确实如此。服务器只是不再监听。您需要获取输入流以查看是否有任何内容。如果没有返回任何内容,则知道连接未起作用。
更新:
使用定时器确定服务器是否响应。
Long currenttime = System.currentTimeMillis();
while(System.currentTimeMillis() - currentTime < x){ //x = miliseconds you want to wait
    (try to read from server)
}

如果执行时间超过x秒,它将超时,你可以在while循环后进行一些错误捕获。

好的,我明白了。我会更新我的问题,并附上我读取数据的方法,这可能是问题所在。 - user2914191

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接