I have a pretty simple Asynchronous UDP listener, setup as a service, and it's been working quite well for awhile now, but it recently crashed on a SocketException An existing connection was forcibly closed by the remote host
. I have three questions:
My code looks something like the following:
private Socket udpSock;
private byte[] buffer;
public void Starter(){
//Setup the socket and message buffer
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpSock.Bind(new IPEndPoint(IPAddress.Any, 12345));
buffer = new byte[1024];
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}
private void DoReceiveFrom(IAsyncResult iar){
try{
//Get the received message.
Socket recvSock = (Socket)iar.AsyncState;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = new byte[msgLen];
Array.Copy(buffer, localMsg, msgLen);
//Start listening for a new message.
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
//Handle the received message
Console.WriteLine("Recieved {0} bytes from {1}:{2}",
msgLen,
((IPEndPoint)clientEP).Address,
((IPEndPoint)clientEP).Port);
//Do other, more interesting, things with the received message.
} catch (ObjectDisposedException){
//expected termination exception on a closed socket.
// ...I'm open to suggestions on a better way of doing this.
}
}
The exception is being thrown at the recvSock.EndReceiveFrom() line.
From this forum thread, it seems that the UDP socket is also receiving ICMP messages and throwing exceptions when they are received. Maybe this is great for low level status updates, but I found it annoying.
First, define the magic number
public const int SIO_UDP_CONNRESET = -1744830452;
Then set the low level io control to ignore these messages:
var client = new UdpClient(endpoint);
client.Client.IOControl(
(IOControlCode)SIO_UDP_CONNRESET,
new byte[] { 0, 0, 0, 0 },
null
);
I've seen that error with UDP if a packet is somehow truncated or otherwise not completely delivered. At least, I think that's what happens. I've never been able to duplicate it reliably.
I would suggest that you catch the SocketException
, log it (if you want), and then dispose of that socket. Then call Starter
again:
catch (SocketException)
{
// log error
udpSock.Close();
Starter();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With