Socket stream hangs when using IOUtils.copy()
I want to send an InputStream
containing XML from the client to a server. Said server manipulates the XML stream using Streaming API for XML (StAX)
and sends it back to the client.
I mange to send the XML to the server, the client receives the answer, but doesn't exit because the server never finishes reading the InputStream
form the client.
But when the server is just dumping the input to System.out
instead of sending something, reading finishes...
edit I forgot to mention that IOUtils.copy()
is running in two separate threads on the client.
Here some code to reproduce this, I've replaced the StAX
part with IOUtils.copy()
on the server.
Server
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
InputStream in = clientSocket.ge开发者_高级运维tInputStream();
OutputStream out = clientSocket.getOutputStream();
IOUtils.copy(in, out);
Client
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)
You must flush and close InputStream and OutputStream. like this:
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;
You are probably creating a deadlock.
- Client - sends data to the server.
- Server - loops data back to the client.
- Client - reads data (that the server looped back)
So, while the client is sending data to the server, the server is sending it back to the client. The client isn't reading that data, it's busy sending.
At some point the TCP buffers fill up, and the server blocks on sending more data to the client. This means the server is blocked on sending data, so eventually the TCP buffers on the receiving side of the server fills up as well, and the client blocks on sending data. Since the client is now blocked on sending, it'll never get to the part where it reads the data that is looped back, so the server will never un-block.
If you're sending a small document, you might not experience this, as all the data fits in the buffers, but once you fill up the buffers, the system will deadlock.
You have to multiplex the sending/receiving. e.g. you could start up a thread on the client that does
InputStream in = socket.getInputStream();
IOUtils.copy(in, System.out)
That way receiving can be done in parallel with the client sending data
Or you could use 2 threads on the server side. One for receiving the data, posting data to be sent back to another thread doing the sending (you'll have to build up an internal queue in this case between the threads).
As far as I remember IOUtils.copy()
does not flush and does not close the stream. It seems that you do not call neither flush nor close too. Try it. I believe that this is your problem.
精彩评论