I am having trouble understanding the differences in how Java handles sockets on Windows and Linux - especially when one of the parties (client or server) closes the connection suddenly.
I wrote the following very simple server and client classes so that my meaning is simple, objective, and easy for you to be as clear as possible:
SimpleClient.java:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; public class SimpleClient { public static void main(String args[]) { try { Socket client_socket = new Socket("127.0.0.1", 9009);
SimpleServer.java:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; public class SimpleServer { public static void main(String args[]) { try { ServerSocket server_socket = new ServerSocket(9009); Socket client_socket = server_socket.accept(); while(true) { BufferedReader in = new BufferedReader(new InputStreamReader(client_socket.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client_socket.getOutputStream()));
Of course, I could implement the code to properly close the client or server, but the goal, as I said, is to simulate a sharp shutdown on both sides, where the “disconnect code” cannot be sent or received. That is why I created these 2 very simple classes.
On Linux, this works very well:
$ java SimpleClient Command: echo Server Received: echo Command: test Server Received: test Command: (server now was closed on the other side) Server was closed on the other side. $
On Windows:
C:\simplesocket>java SimpleClient Command: echo Server Received: echo Command: test Server Received: test Command: (server now was closed on the other side) java.net.SocketException: Connection reset by peer: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(Unknown Source) at java.net.SocketOutputStream.write(Unknown Source) at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source) at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source) at sun.nio.cs.StreamEncoder.implFlush(Unknown Source) at sun.nio.cs.StreamEncoder.flush(Unknown Source) at java.io.OutputStreamWriter.flush(Unknown Source) at java.io.BufferedWriter.flush(Unknown Source) at SimpleClient.main(SimpleClient.java:32)
Let's say I'm trying to ignore this exception by changing the following lines on my SimpleClient.java:
// Send: try { out.write(msg); out.newLine(); out.flush(); } catch(Exception e) {}
Another exception:
C:\simplesocket>java SimpleClient Command: echo Server Received: echo Command: test Server Received: test Command: (server now was closed on the other side) java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at sun.nio.cs.StreamDecoder.readBytes(Unknown Source) at sun.nio.cs.StreamDecoder.implRead(Unknown Source) at sun.nio.cs.StreamDecoder.read(Unknown Source) at java.io.InputStreamReader.read(Unknown Source) at java.io.BufferedReader.fill(Unknown Source) at java.io.BufferedReader.read(Unknown Source) at SimpleClient.main(SimpleClient.java:42)
I don’t know if the corresponding lines of code will contain the ones indicated in these exceptions, but the first one is selected on out.flush () , and the second one on .read () .
So basically, as you can see on Linux, even after the server shuts down suddenly:
1. It does not throw an exception when I try to send data.
2. And more importantly, when I try to get it, the first char is "-1" and received correctly.
On Windows, it throws exceptions both when sending, and, more importantly, when receiving - when the read () method is called - I cannot get the code "end of stream" (-1).
This leads to some questions:
1. Why is there such a big difference in Windows x Linux? Why are these Exceptions not thrown on Linux when they are on Windows?
2 .. Should Java, with all its cross-platform qualities, try to minimize differences when working on both systems? (by the way, I'm using JDK 7 on both)
3. Is there a way to change the code for a sudden shutdown and make it work more "Linux-like" on Windows without throwing all these Exceptions and getting -1 on my in.read () ??
4. If not, is it recommended to use any external API?
I tried searching the Internet for hours on this particular topic, but to no avail.
I have also tried many solutions like calling methods isConnected () , isBound () , isClosed () , etc. In client_socket, on the client side without success. They always say that there is an active connection and no problems with it, even after closing the server.
I hope someone finds the time to answer at least one of these questions.
For any answers you thank me in advance.