简体   繁体   中英

Java socket read not receiving write sent immediately after connection is established

I have a java client and server I'm trying to write Junit tests. In my tests I wait for a connection between the server and client to be made, and then write a message to from server to client to test the communication. I've discovered if I do the write immediately It isn't received and the client stays blocked on the BufferedReader.readLine() method. If I add a sleep for half a second between the socket connection and the server write call everything works perfectly.

I'm trying to figure out why the sleep is needed. I know that the socket has been generated and a bufferedReader wrapped around it's input stream before my waitForConnection() method returns with a report that server and client have connected. My best guess is that I need to ensure that I call the readLine method of the client before the server calls it's write method; but I thought that sockets would automatically buffer input that came in and wasn't read immediatly?

Can anyone confirm (or disprove) my suspicion that I have to guarantee the client has called readline before the server calls write. And if this is required can anyone suggest a way that the server can detect if the client is ready to receive input without having to implement another handshake in addition to the TCP handshake?

edit: I should have said this sooner, but the test that is failing is testing an ability to restablish a connection when the old one fails. After the client connects my mock server kills the socket/serverSocket and a few seconds later reopens a new serverSocket and accepts a new connection from the client. It's after the client establishes a connection for the second time that the write failes. My earlier tests that just test a connection occures and the client receives a write appear to work.

Thanks

Can anyone confirm (or disprove) my suspicion that I have to guarantee the client has called readline before the server calls write.

You don't. The server can send any time it likes.

And if this is required

It isn't.

Your problem lies elsewhere.

I had the same problem and even thought about a cumbersome acknowledgement process. But in fact you do not need to wait for the read to get called and the problem is located somewhere else.

In my case the I delegated the reading call to a separate thread. But the jUnit test was finishing successfully although the read in the thread

  • didn't get called yet,
  • was still in reading process or
  • even worse: the thread didn't even reach running state

when the main jUnit-Thread already terminated.

To prove my assumption you could put the wait at the end of the unit test instead "between the socket connection and the server write call" and the sending/receiving will still work.

Just for completeness: do not forget to call flush()

You do not need to make sure the client is reading before server writes. The network layer will buffer the traffic until it is consumed.

Make sure to call flush on the OutputStream after issuing the message on the server. Otherwise, actual network call may not be made until buffer fills up. Also, your use of readLine may be problematic. Perhaps you aren't issuing line termination character? It may be better to use the more basic read( char[] ) method.

How you destroy the server socket in your unit test? May be you close the socket before the data is sent.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM