a exception is generated in Windows but not in Linux

FULL PRODUCT VERSION :

junmin@Linux:~/Workspace/JMessenger/build/classes$ java -version

java version "1.6.0"

Java(TM) SE Runtime Environment (build 1.6.0-b105)

Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

E:\JMessenger\build\classes>java -version

java version "1.6.0_01"

Java(TM) SE Runtime Environment (build 1.6.0_01-b06)

Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :

junmin@Linux:~/Workspace/JMessenger/build/classes$ uname -a

Linux Linux 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux

ubuntu feisty, installed sun-java-jre and jdk from the repository of ubuntu

and

Windows XP professional sp2

java6 installed

A DESCRIPTION OF THE PROBLEM :

reader =new BufferedReader(new InputStreamReader(client.getInputStream()));// client is the socket in the server side

try{

while((incomingMessage = reader.readLine()) !=null){

}

}

catch(Exception e){

System.out.println(e);

}//server

this is a client-server program, why in Windows it(server) throw the Exception when the client closes the program o the socket? and it doesnt throw any exception in Linux(ubuntu feisty/dapper) ?

here is the exception generated in Windows:

java.net.SocketException: Connection reset

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.readLine(Unknown Source)

at java.io.BufferedReader.readLine(Unknown Source)

at Service.run(Service.java:37)

is this could be considered a bug? i hope java can throw the same exception in Linux too, cause this helps to check the statu of socket connection. thanks

[2528 byte] By [junmina] at [2007-11-27 1:54:44]
# 1

Did you try a Windows client and Linux server or vice versa?

It's unclear whether this is a server's issue to detect the closed socket, or a client issue to properly notify the socket being closed.

It is quite eerie that the correct behavior is provided in Windows and not in Linux.

SlugFillera at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 2
Under Linux I would expect the readLine() to return null.Apparently Unix-based systems do a proper socket close on behalf of an exiting process. Windows systems just reset the socket. It's debatable which is correct.
ejpa at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 3

to ejp:

i think you are right...

in my app, the server side detects that the client disconnects if it gets this exception, but i am now working on linux now, this will never work again, can i do anything similar to this? what would you recommend me how to detect if the client disconnects?

junmina at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 4
I answered that. readLine() will return null. You can't tell the difference in this case between an orderly close and a panic attack, but that's outside Java's control.
ejpa at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 5
got it, thx
junmina at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 6
> Apparently Unix-based systems do a proper socket close on behalf of > an exiting process.Every open file descriptor (including pipes and sockets) is closed on the exit of a Unix process.
BIJ001a at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 7

And on the exit of a Windows process too, so that doesn't explain anything. And on the exit of a process in every other operating system I have ever used except (of course) NetWare :-|. And the normal close() operation would start a TCP FIN/CLOSING/LAST-ACK/FIN-WAIT-1/FIN-WAIT-2/TIME-WAIT sequence. This doesn't happen on Windows. So evidently Windows does a prescan of open sockets to reset them. And arguably it shouldn't do that.

ejpa at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 8

> And on the exit of a Windows process too, so that doesn't explain anything.

It is not obvious that the pipes and sockets are treated similarly to the open files, that they contend for the same file descriptors etc, so even if my modest contribution did not explain anything, it still might have contained some pieces of information.

BIJ001a at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 9

The following is mostly an educated guess, but it is based in some understanding of how the different OSs work.

In linux sockets are handled by the driver(read: kernel part) that converts the actions on file descriptors to actions on network sockets. When a program shuts down, said driver continues to run, but receives a close request on the file descriptor, so it proceeds with a standard socket close.

On windows, the sockets are the property of the program, not the network driver, and when the program shuts down the sockets simply abort as they are discarded. The network driver is not allowed to temporarily hold the socket until its operation completes. They are simply thrown away.

Anyway, a proper solution that would be helpful for all OSs is to actually close the socket within the program, rather than hope the OS has a "garbage collector" for sockets. The same applies for all OS resources(files, pipes, GUI resources, etc). On certain OSs, certain resources may actually remain allocated after program shutdown, if not formally disposed.

On a side note, socket libraries for windows usually support socket auto-close on disposing of the socket object. I'm surprised the Java library doesn't (seem to) follow the same pattern. Then again, I've seen programs(non-java, of course) cause system freezes over stuff like that.

SlugFillera at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...
# 10

OK, I was a little hasty. I've thought about this some more, and SF is on the right track.

In Windows, sockets and their descriptors are an artefact of the WINSOCK subsystem which isn't tied terribly closely to the kernel: it's more of a conduit directly to the NDIS subsystem really. These descriptors are not kernel fds and they're not managed by the kernel (e.g. auto-closed on exit). So it is up to WINSOCK what to do with open sockets when a process exits. If WINSOCK just threw the socket away, the other end wouldn't get a 'connection reset' on a read, it would just block forever. It would get an RST on a write. So from the observed behaviour it is clear that WINSOCK actively issues an RST for sockets that are still open when a process exits.

In Unix and other sane operating systems which haven't invented their own semantics for 20-year-old protocols, a socket is a kernel fd and it is close()d by the kernel when the process exits: this is indistinguishable from the case where the process close()s it itself, so the FIN/ACK sequence occurs.

ejpa at 2007-7-12 1:26:50 > top of Java-index,Core,Core APIs...