views:

640

answers:

2

I have a loop that opens a socket, acts on the socket, then closes the socket and restarts. However, on the second iteration I get SocketException, Only one usage of each socket address (protocol/network address/port) is normally permitted.
However, the socket should be closed, netstat -a doesn't show that I'm listening on that port or anything. The code that throws the exception is:

_bindedLocalSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_bindedLocalSocket.Bind(new IPEndPoint(Util.ChannelProfileToListeningAddress(_profile), _profile.ListenPort));
_bindedLocalSocket.Listen(30);
_bindedLocalSocket.BeginAccept(new AsyncCallback(OnRequested), null);

However, I think the culprit is not that code, just before I get to that code, and before I try to close the connection I get this:

An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at Poderosa.PortForwarding.SynchronizedSocket.EndReceive(IAsyncResult ar)
   at Poderosa.PortForwarding.Channel.OnSocketData(IAsyncResult result)

Once I close the program and run it again, it can make the first connection fine, the second one acts just the same (SocketException). Does anybody have any idea how I can fix this?

A: 

It's a known issue on windows, that even if you've closed a socket, there is a waittime before the resource is released back to the OS.

There is a way to manually set the waittime for a socket in .NET, however it may be a better option to revisit your design, to instead keep the listener socket open, instead of closing it down, and instead close the new socket that is created during Socket.Accept();

Alan
If I don't close the socket, it get's closed at the other end and I'm not in control of it. I'm running rsync over the socket which is a port forwarded SSH connection (from a windows machine port 873 to the rsync machine port 873). So I can't change that, is there a workaround?
Malfist
I put a 30 second sleep and it didn't help.
Malfist
Try Ryeguy's solution with SetSocketOption.I wasn't aware that a remote connection could close a listener socket.
Alan
+3  A: 

I thought that socket.Close() took care of that, but I guess not. In that case, you need to use:

socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

You can read more about socket options here.

ryeguy
this fixes that issue but now I run into problems with my program trying to access a disposed Socket :(
Malfist
If you're using socket.close(), I believe you have to make a new socket object all together. If you want to use the same object, I think you have to use socket.disconnect(). Look at the MSDN docs - I'm not 100% sure, but I'm pretty sure that's what disconnect is made for.
ryeguy
I'm closing the SSHConnection which handles closing the socket, or is supposed to...
Malfist