|
Technote 1157Don't println to a SocketBy Jens Alfke |
CONTENTSDoes This Ring a Bell? | A common cause of deadlocks in client-server Java applications when running on Mac OS stems from improper use of the |
Does This Ring A Bell?You've written a networked client application or applet that communicates with a server using either a standard Internet protocol like HTTP or FTP, or a custom protocol that uses a similar line-oriented syntax. Your application works fine on Windows and Unix, but when you run it on a Mac, the client gets stuck when it tries to receive a response from the server. If you check the server, you find that the thread communicating with your app is similarly blocked reading a command from the client. Chances are you've just run into a little-known Java networking gotcha (we've seen many reports of this from developers.) The bad news is that it's a bug in your app, not in MRJ. The good news is that it's easy to work around. |
println Considered HarmfulThe underlying problem is a confusion between different line-breaking conventions. Line-based Internet protocols almost universally use CRLF as a line break -- that is, an ASCII carriage return ( The problem is that Here's what happens: Your client calls When running in MRJ, this sends the bytes:
The server receives the text and the CR, then expects a LF to follow the CR and waits to receive one. Actually, most servers are smart enough that if the character received following the CR is not an LF, they'll understand the nonstandard line break and treat the second character as the start of the next line. But in any case, the server typically waits for the second character before processing the command. Meanwhile, the client waits to receive a response line from the server before sending any more text. Both sides are blocked in |
The Easy FixThe lesson here is not to use
This is pretty simple, but unfortunately requires changing all of the The really nice fix that won't workThere's a really nice fix that is, unfortunately, not possible. If you look at the source to the Fixing the serverIf you happen to be developing the server as well, and can make changes to its code, then there's an even better fix you can make on the server side instead of changing the client. In the previous section, I described how the server blocks waiting for a character to follow the CR so it can tell whether it's an LF or not. A more intelligent way to handle nonstandard line breaks is for the server to process the input line immediately once it receives the CR, but to set a flag that indicates that if the next character received is an LF it should be ignored. This way the server will not block after it receives the CR, will process the command and return a response, and the client code will receive the response and continue running. No deadlock. |
Thanks to the usual suspects.