I am writing a loop which will listen on a given port for incoming UDP
packets. If the UDP sender (client), terminates abnormally, then my call to
socket.BeginReceiveFrom throws a SocketException. I catch this exception,
then re-create the socket, and re-bind it. The next time I call
BeginReceiveFrom, I get that same exception again (" An existing connection
was forcibly closed by the remote host").
When writing a simple loop to listen for UDP packets, what is the right way
to handle this exception? Here's my existing code (the async callback
"DataReceived" is included, too).
Thanks
Greg
public void StartReceiveFrom ()
{
Log (string.Format ("Started UDP Receiver {0} on local port {1}", Name,
localPort));
Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
try
{
IPHostEntry localHostEntry = Dns.GetHostByName(Dns.GetHostName());
IPEndPoint localIpEndPoint = new IPEndPoint(localHostEntry.AddressList[0],
localPort);
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, 1);
socket.Bind(localIpEndPoint);
while (true)
{
IPEndPoint remoteIpEndPoint = new IPEndPoint (IPAddress.Any, 0);
SocketReceiveStateObject stateObject = new SocketReceiveStateObject ();
stateObject.socket = socket;
stateObject.remoteIPEndpoint = remoteIpEndPoint;
stateObject.updListener = this;
stateObject.name = Name;
EndPoint tempRemoteIpEndPoint = (EndPoint)remoteIpEndPoint;
try
{
socket.BeginReceiveFrom (stateObject.buf, 0, stateObject.buf.Length,
SocketFlags.None, ref tempRemoteIpEndPoint, new AsyncCallback(DataReceived),
stateObject);
stateObject.done.WaitOne();
if (stateObject.DataReceivedException != null)
{
throw stateObject.DataReceivedException;
}
}
catch (SocketException ex)
{
// Log (ex.ToString());
try
{
socket.Close ();
}
catch
{
}
Log ("Recreating listening socket in StartReceiveFrom()");
socket = new Socket (AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress, 1);
socket.Bind(localIpEndPoint);
}
}
}
catch (ThreadAbortException)
{
Log (Name + " aborted... closing socket");
socket.Close();
}
}
public void DataReceived (IAsyncResult asyn)
{
SocketReceiveStateObject stateObject =
(SocketReceiveStateObject)asyn.AsyncState;
try
{
EndPoint tempRemoteEndPoint = (EndPoint)stateObject.remoteIPEndpoint;
int bytesreceived = stateObject.socket.EndReceiveFrom (asyn, ref
tempRemoteEndPoint);
stateObject.remoteIPEndpoint = (IPEndPoint) tempRemoteEndPoint;
stateObject.updListener.OnUdpDataReceived (new UdpDataReceivedEventArgs
(stateObject.buf, stateObject.remoteIPEndpoint));
if (AdelaP2PLib.Globals.LogEveryUdpSocketReceive)
{
Log (string.Format("{0} Socket LocalEndPoint {1}, RemoteEndPoint {2}",
stateObject.name, stateObject.socket.LocalEndPoint, tempRemoteEndPoint));
}
}
catch (System.Net.Sockets.SocketException ex)
{
// Log (ex.ToString());
stateObject.DataReceivedException = ex;
}
catch (ObjectDisposedException)
{
Log ("UdpListener.DataReceived: Socket has been closed (probably due to
listener thread aborting)");
}
finally
{
stateObject.done.Set();
}
}