【问题标题】:Socket stream hangs when using IOUtils.copy()使用 IOUtils.copy() 时套接字流挂起
【发布时间】:2010-12-01 14:52:06
【问题描述】:

我想将包含 XML 的 InputStream 从客户端发送到服务器。所述服务器使用Streaming API for XML (StAX) 操作 XML 流并将其发送回客户端。

我设法将 XML 发送到服务器,客户端收到答案,但没有退出,因为服务器从未完成从客户端读取 InputStream。 但是当服务器只是将输入转储到System.out 而不是发送某些内容时,读取完成...

edit我忘了提到IOUtils.copy() 在客户端的两个单独线程中运行。

这里有一些代码可以重现这一点,我在服务器上用IOUtils.copy() 替换了StAX 部分。

服务器

ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();

InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);

客户

Socket socket = new Socket(host, port);
FileInputStream fin = new FileInputStream(file);
OutputStream out = socket.getOutputStream();
IOUtils.copy(fin, out)

InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)

【问题讨论】:

    标签: java sockets apache-commons-io


    【解决方案1】:

    您必须刷新并关闭 InputStream 和 OutputStream。 像这样:

    ServerSocket serverSocket = new ServerSocket(port);
    Socket clientSocket = serverSocket.accept();
    
    InputStream in = clientSocket.getInputStream();
    OutputStream out = clientSocket.getOutputStream();
    IOUtils.copy(in, out);
    
    //add 
    out.flush();
    in.close();
    out.close;
    

    【讨论】:

      【解决方案2】:

      您可能正在创建一个死锁。

      • 客户端 - 向服务器发送数据。
      • 服务器 - 将数据循环回客户端。
      • 客户端 - 读取数据(服务器环回)

      因此,当客户端向服务器发送数据时,服务器正在将数据发送回客户端。 客户端没有读取该数据,它正忙于发送。

      在某些时候,TCP 缓冲区会填满,服务器会阻止向客户端发送更多数据。这意味着服务器在发送数据时被阻塞,因此最终服务器接收端的 TCP 缓冲区也被填满,客户端在发送数据时被阻塞。由于客户端现在在发送时被阻塞,它永远不会到达它读取环回数据的部分,因此服务器永远不会解除阻塞。

      如果您要发送一个小文档,您可能不会遇到这种情况,因为所有数据都适合缓冲区,但是一旦您填满缓冲区,系统就会死锁。

      您必须复用发送/接收。例如你可以在客户端上启动一个线程

      InputStream in = socket.getInputStream();
      IOUtils.copy(in, System.out)
      

      这样接收可以与客户端发送数据并行进行

      或者您可以在服务器端使用 2 个线程。一个用于接收数据,将数据发送回另一个执行发送的线程(在这种情况下,您必须在线程之间建立一个内部队列)。

      【讨论】:

      • 我忘了提到 IOUtils.copy() 在客户端的两个单独线程中运行。现在添加为编辑。
      • 在这种情况下,客户端何时关闭到服务器的输出流? (或者,谁在什么时候关闭任何流?)
      【解决方案3】:

      据我所知,IOUtils.copy() 不会刷新也不会关闭流。似乎您也没有调用既不刷新也不关闭。试试看。我相信这是你的问题。

      【讨论】:

      • 我省略了关闭和刷新以减少混乱(也许不是一个好主意)。
      猜你喜欢
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 2016-09-06
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多