使用IOUtils.copy()时套接字流挂起

时间:2010-12-01 14:52:07

标签: java sockets apache-commons-io

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

我可以将XML发送到服务器,客户端会收到答案,但不会退出,因为服务器永远不会从客户端读取InputStream。 但是当服务器只是将输入转储到System.out而不是发送内容时,阅读结束......

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

这里有一些重现此代码的代码,我已将[{1}}部分替换为服务器上的StAX

服务器

IOUtils.copy()

客户端

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

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

3 个答案:

答案 0 :(得分:4)

您必须刷新并关闭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;

答案 1 :(得分:3)

你可能正在制造僵局。

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

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

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

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

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

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

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

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

答案 2 :(得分:1)

据我所知,IOUtils.copy()不会刷新并且不会关闭流。看来你既不会打电话也不打电话。试试吧。我相信这是你的问题。