tags:

views:

253

answers:

3

I am having a few issues with sockets within my Java SIP client. When I bind to an address and port, if something goes wrong I have to attempt to reconnect, usually after I've stopped and restarted the process. Problem with that is then the port is bound and I am forced to increment the local port.

How can I remove the binding to the port I am targeting before binding to it?

If that isnt possible, then how can I trap the process just before it ends so that I can locate the socket binding and close it manually?

@Jason - Jason, but in this case I am writing the Client and have no access to the server, the port I am referring to is on the client and is local. Is there a way to flush the port binding before attempting to connect? If not is there a way to trap the process interrupt, as in perl there is a way to trap a 'die' signal and do some post processing, does Java have this? If so I could call close() on the socket connection

+3  A: 

In my experience 9 times out of 10, the answer to this class of problem is, "Look up SO_LINGER".

If you pull the plug (literally) on a client, the server optimistically hopes it will come back to collect the data you already sent on that socket. So it holds onto that data, and the port, until the buffers clear.

Usually on the server you want to kill these buffers with extreme prejudice, due to the sort of DOS attack (intentional or accidental) you just discovered.

Jason
very interesting. I've seen some stuff with java sockets where like two java servers seem to bind to the _same_ port! Wonder if its related.
Justin
Jason, but in this case I am writing the Client and have no access to the server, the port I am referring to is on the client and is local. Is there a way to flush the port binding before attempting to connect? If not is there a way to trap the process interrupt, as in perl there is a way to trap a 'die' signal and do some post processing, does Java have this? If so I could call close() on the socket connection
Matt1776
It should still work, yes. Generally when you're the one making a connection, the originating port doesn't really matter (are you doing something with hole-punching in a firewall?), but once the socket is created, the TCP-IP stack doesn't care who originated the request. Your kernel will still hold onto packets for connections you believe you're done with, unless you tell it not to.
Jason
What should still work? I am confused by your responses. My question is how can I clear the local port binding caused by the client? When the client next connects, as in when I reboot the process, I want to be able to clear the port binding to ensure there are no conflicts. How can that be done?
Matt1776
Back to my original suggestion: Just try setSoLinger(false, 0) and see if that fixes your problem. Long version: An open socket is an open socket. When the guy on the other end goes away, there is cleanup code which doesn't do what pretty much anyone who has written software in the last 20 years wants it to do (I first encountered this problem in 1992, and found ample advice on Usenet). It is on by default. If you want to reuse an address, you have to change the defaults.
Jason
I see - Ok, thank you, I will give that a shot.
Matt1776
A: 

Don't fiddle with SO_LINGER, it just adds insecurity. The real question is why are you binding to a local port at all?

EJP
To listen for incoming packets? Im not actually doing the binding - its the library, JAIN-SIP::SipProvider - ListeningPoint. If I can trap the program exit I can call destructor method on the listening point but no one seems to know how I can do that. In perl I can trap anything
Matt1776
But you don't have to bind an outgoing socket to a local port at all. The system will choose one for you, and a new one every time. I did some work with JAIN-SIP last year and never noticed this problem. Are you setting some configuration item that is forcing the local port to a single value?
EJP
EJP - the ListeningPoint binds the SipProvider stack to a local IP and a local Port for the purposes of listening to incoming responses from the target client or server - This is not outgoing, its incoming. When the program is stopped the port is still bound and when I go to restart the program I have to increment the local listening port - if I dont, I get a 'port already in use' error
Matt1776
"Don't fiddle with SO_LINGER, it just adds insecurity." I'm genuinely curious to know how it adds insecurity. Or did you simply mean he's barking up the wrong tree?
Jason
Disabling SO_LINGER disables the TIME_WAIT state which is an essential part of TCP/IP security. Without it, there is ambiguity between two successive connections between the same pair of ipaddress:ports. This is discussed in the RFCs and the major textbooks such as Stevens.
EJP
A: 

Ok - I found a way to trap Java signals by reading this tutorial online - http://www.ibm.com/developerworks/java/library/i-signalhandling/

This way one can trap the die signal and close the connection.

Matt1776