Reputation: 5261
My C# .net application currently does the following (among other things):
When my application restarts, but the external application does not close, the socket doesn't seem to ever close. Then when I try to start up communication on that port again I get an error. However, as soon as I close the external application I am able to open a socket on that port.
It seems like my program is not closing down properly. It should be killing the socket when it exits, however when the external process is running that socket never closes.
Any ideas?
Upvotes: 8
Views: 5907
Reputation: 11
Another solution got from the awnser.
If you must set ProcessStartInfo.UseShellExecute
to false
to use the redirect/dispose of the input stream, a better solution is to set socket handle option to prevent the inheritance by the child process.
It can be done via a P/Invoke SetHandleInformation
on the socket handle whick can be obtained from TcpListener.Server.Handle
or anywhere:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetHandleInformation(IntPtr hObject, uint dwMask, uint dwFlags);
private const uint HANDLE_FLAG_INHERIT = 1;
private static void MakeNotInheritable(TcpListener tcpListener)
{
var handle = tcpListener.Server.Handle;
SetHandleInformation(handle, HANDLE_FLAG_INHERIT, 0);
}
Upvotes: 0
Reputation: 2975
This is just a stab because I have seen how you're starting the external process. If you're creating a Process object, my guess is you're not setting:
ProcessStartInfo.UseShellExecute = true;
If UseShellExecute is set to false, the child process will inherit open socket handles from the parent process. This will keep your socket open even if the parent application is closed.
Upvotes: 17
Reputation: 4174
The first thing is to take a look on the socket state when the application is closed. The socket could be in the TIME_WAIT state that means that it will wait for some time in order to make sure that no other messages will be received. You can read about that here: http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ Now the TIME_WAIT state will be generated on the socket according to which of them initiated the connection termination procedure. So if for some reason your socket perform the close action in the server site then in the server site ( in the server's port ) the socket will change the state to the TIME_WAIT, so if you restart your server application during the socket is in TIME_WAIT a new socket will fail to bind to the listening port, I thing that this is the problem you met.
Upvotes: 0
Reputation: 17186
From what I found here my suspicion might be confirmed that this is a case of the new process inheriting handles from the parent, thus causing your issue.
It looks like you can just copy/paste the code from that link to do a direct call to the Windows CreateProcess API with the flag set so as to not inherit handles.
Another separate idea is to write an intermediate launcher program that takes the command line information and then launches and then quits. This extra indirection might get you where you need to be with very little effort.
Upvotes: 1
Reputation: 567
You might be able to solve this with the using keyword
using (Socket socket = new Socket()) {
//The code
}
Does the other application use the socket at all?
Upvotes: 0