TCP Socket Hangs while receiving in Java
I am using a TCP Socket in my Java application. I am trying to receive byte data from some device with the readInt()
method.
This method works fine if I get 4 bytes from the device. But if I get开发者_C百科 less than 4 bytes, or nothing, then readInt()
hangs. It's blocked and doesn't return. It should throw EOFException
exception if no data is there to receive, but it's hanging.
Code:
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream din = new DataInputStream(socket.getInputStream());
int res = din.readInt();
An EOFException
doesn't get thrown until the socket closes.
This method should block when you try to read more data than is available. It returns EOFException only when the socket closes, as this is the actual EOF condition. If the socket remains open, it blocks until it has enough data to fill the request.
This is part of the fundamental nature of the way sockets work. For Java to behave any differently, it would have to incorrectly implement socket behavior.
When putting together your socket protocol, you should consider this. Why are you waiting for an int to be received and only part of an int is being sent? This should never happen. If you want to send different types of data, you should include some sort of header byte first to tell the receiver what kind of data is coming next so it knows how to process it and what to do with it.
That exception is probably only thrown when the other side of the connection closes the socket. Otherwise the receiving side has no indication that no more data is going to come, so it waits (you did tell it to get at least four bytes when you called readInt
). You will have to read bytes and parse them into application blocks yourself.
The classes you are using form part of the java.io
package which performs blocking I/O. The correct solution is to switch to using the non-blocking I/O classes defined in java.nio
. Be warned that writing a non-blocking I/O application is non-trivial. However, it is the only solution to avoiding having your I/O thread potentially block indefinitely.
Note that as a hacky solution you could use a dedicated blocking I/O thread that simply reads and adds bytes to a BlockingQueue
being polled by another thread. The consumer thread could call poll(long, TimeUnit)
on the BlockingQueue
with a reasonably long time-out value, and if the call returned null
it could take this to mean that no more data was available. Note that this is a fairly ugly solution as it means your I/O "producer" thread would remain blocked at this point.
That situation can only arise if you have mis-implemented your application protocol. How come you're expecting a 4-byte integer and the application is only sending 1-3 bytes? Is it really sending a binary int? or should you perhaps be reading and parsing an ASCII string?
精彩评论