views:

431

answers:

5

I have a socket tcp connection between two java applications. When one side closes the socket the other side remains open. but I want it to be closed. And also I can't wait on it to see whether it is available or not and after that close it. I want some way to close it completely from one side. What can I do?

+2  A: 

Both sides have to read from the connection, so they can detect when the peer has closed. When read returns -1 it will mean the other end closed the connection and that's your clue to close your end.

nos
My code is a multi-threaded code and I can not waste one of my threads for just looking at connection and finding whether it is closed or not. I should mention that I have thousands of these connections not just one.
Shayan
Then you will have to switch to NIO and do multiplexed IO. You have to read from the socket one way or another if you want to detect a graceful close from the peer.
nos
A: 

You probably want to have a connection pool.

Roman
No. Just closing the connection automatically.
Shayan
+3  A: 

If you are still reading from your socket, then you will detect the -1 when it closes.

If you are no longer reading from your socket, go ahead and close it.

If it's neither of these, you are probably having a thread wait on an event. This is NOT the way you want to handle thousands of ports! Java will start to get pukey at around 3000 threads in windows--much less in Linux (I don't know why).

Make sure you are using NIO. Use a single thread to manage all your ports (connection pool). It should just grab the data from a thread, forward it to a queue. At that point I think I'd have a thread pool take the data out of the queues and process it because actually processing the data from a port will take some time.

Attaching a thread to each port will NOT work, and is the biggest reason NIO was needed.

Also, having some kind of a "Close" message as part of your stream to trigger closing the port may make things work faster--but you'll still need to handle the -1 to cover the case of broken streams

Bill K
This side doesn't know whether it is finished or not. Also sending a close message from the other side's overhead is too much. most of the times for one message we send two messages.
Shayan
I'm not sure what you mean, but you can simply end a message with a special character or bytecode in order to tell the listener that it's the last message. It is pretty much free.
Bill K
If sending a few extra bytes to signal a close is too much overhead, then you either have very special requirements or you are suffering from premature optimization.
Confusion
+2  A: 

The usual solution is to let the other side know you are going to close the connection, before actually closing it. For instance, in the case of the SMTP protocol, the server will send '221 Bye' before it closes the connection.

Confusion
Although this is a good optimization, it will not handle dropped connections and eventually you will pile up open ports. This is not acceptable in a system with thousands of ports open, but it does reduce the frequency of "Can I close this port" scans.
Bill K
+2  A: 

TCP doesn't work like this. The OS won't release the resources, namely the file descriptor and thus the port, until the application explicitly closes the socket or dies, even if the TCP stack knows that the other side closed it. There's no callback from kernel to user application on receipt of the FIN from the peer. The OS acknowledges it to the other side but waits for the application to call close() before sending its FIN packet. Take a look at the TCP state transition diagram - you are in the passive close box.

One way to detect a situation like this without dedicating a thread to each socket is to use the select/poll/epoll/kqueue family of functions. The socket being passively closed will be signaled as readable and read attempt will return the EOF.

Hope this helps.

Nikolai N Fetissov