Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Java NIO socket communication: why can I still send data after the server closed the connection?

 
Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15484
43
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm using the Java NIO API for socket communication (in blocking mode).

I noticed that when the remote host closes the connection, my client doesn't notice it - the client can still send data and doesn't get an exception, as if the data has been sent successfully. Have a look at the code below, which does the following: Start a very simple server, which accepts a connection and closes it after a short delay of 200ms. The client opens a connection, which the server accepts. Before sending data, the client waits one second, so that the server has closed the connection in the meantime. Then the client sends some data.

I would expect that an exception would happen in the client when trying to send the data, because the server has already closed the connection. However, this doesn't happen. Why not, and how can I detect if the connection is still open and can be used to send data? Calling channel.isConnected() doesn't work - it will return true even after the server has already closed the connection.

Output:

Client connected
Server accepted client connection
Server closed connection
Client sent 4 bytes
Client closed connection
 
Jesper de Jong
Java Cowboy
Saloon Keeper
Posts: 15484
43
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've found out myself why this happens. It has to do with how TCP/IP works.

TCP/IP is a connection-oriented protocol: you make a connection, then you can send and receive data, and at the end you close the connection. However, TCP is built on top of IP, which is a packet-oriented protocol. Some of this shows through the TCP protocol (it's a leaky abstraction - you're not supposed to be bothered with how TCP is implemented under the covers, but inevitably you have to deal with some of the implementation details anyway).

So, when the remote system closes the connection, the client might not notice it immediately, and it seems like you can still send data to the remote system. It will take a while before the client notices that no acknowledgements are received anymore.

One way to solve this is to define a disconnect message at the application-level protocol; in other words, the remote host should send the client a "I'm going to close the connection now!" message before really closing it.
 
James Kirk
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi there,
I am digging out a rather old post, but it perfectly describes my question. My problem with the above setup is: The sending side only seems to recognize the dropped connection, if I send more data than I actually intend to (probably one has to send more than fits in the sockets send buffer). So my question is: can I safely detect if a connection has been dropped without an extra acknowledge mechanism?

Many TIA,
-- JK
 
Campbell Ritchie
Sheriff
Pie
Posts: 50232
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don’t know myself, but welcome to the Ranch
 
James Kirk
Greenhorn
Posts: 7
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Don’t know myself, but welcome to the Ranch


Thanks a lot!

I have been searching for a good Java forum quite a while. Now I finally found one (-:
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic