【问题标题】:Java writing to closed output stream not throwing ioexceptionJava写入关闭的输出流不抛出ioexception
【发布时间】:2016-11-26 18:55:18
【问题描述】:

这是我的客户端/服务器的流程。

在主线程中创建套接字。

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

如何检测socket被关闭的问题?

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();
    }

永远不会抛出异常。它说Written 60 bytes。有什么想法吗?


更新

这是我阅读回复的方式。我等待数据,读取前 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 吗?如果您要关闭所有内容,那么它也应该抛出它。
  • 是的,没有抛出异常。我用有关线程之间传递的套接字的其他信息更新了问题
  • 你可以从一个封闭的流中读取多少字节而不阻塞?没有。所以available() 必须返回零。
  • 您没有写入已关闭的输出流。您正在写入可能已被对等方关闭的连接。这不是一回事。

标签: java sockets outputstream


【解决方案1】:

它说它写了 60 个字节,因为它确实写了。服务器只是不再听了。您需要获取输入流以查看是否存在任何内容。如果什么都没有返回,那么您就知道连接没有工作。

更新

使用计时器来确定服务器是否正在响应。

Long currenttime = System.currentTimeMillis();
while(System.currentTimeMillis() - currentTime < x){ //x = miliseconds you want to wait
    (try to read from server)
}

这样如果时间超过 x 秒,就会超时,你可以在 while 循环之后做一些错误捕捉

【讨论】:

  • 好的,我明白了。我会用我读取数据的方法来更新我的问题,这可能是这里的罪魁祸首。
【解决方案2】:

当服务器关闭它的 TCP 连接端时,它会发送一个 FIN 数据包告诉客户端。客户端程序将此视为 InputStream 到达终点。此外,如果客户端尝试写入,服务器将发送一个 RST 数据包来表示错误。如果客户端程序在收到 RST 后尝试写入,API 将抛出带有消息“连接重置”的 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

【讨论】:

    猜你喜欢
    • 2011-09-10
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 2014-01-05
    • 2013-04-03
    • 1970-01-01
    相关资源
    最近更新 更多