I have a .NET Framework 4.8 application (Windows service) which sends and receives data over UDP. Sometimes, randomly, on one of the ports, when calling socket.BeginReceiveFrom, the exception with error code 10054 is thrown
The code:
NOTE: This code is just snippet. This is not fully functional solution equipped with error handling
private Socket serverSocket = null;
private byte[] byteData = new byte[1024];
private void DoReceiveFrom(IAsyncResult iar)
{
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int dataLen = this.serverSocket.EndReceiveFrom(iar, ref clientEP);
if (dataLen > 0)
{
// Do something with the data
}
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
// This is the part which throws an exception randomly
this.serverSocket.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
}
The error:
"System.Net.Sockets.SocketException (0x80004005): The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress
at System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
at System.Net.Sockets.Socket.BeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP, AsyncCallback callback, Object state)"
There are about 10,000 simultaneously "connected" clients (remote controllers connected via cellular network)
The program listens on approximately 30 UDP ports, and controllers are distributed roughly evenly across the ports
Each controller sends/receives about 10 small data packets per minute
I can't just "ignore" this error (as recommended on some internet posts), because after BeginReceiveFrom fails with an exception, the socket cannot receive other data
The only practical way I've found is to close current socket and create the new one, binded to the same port. This doesn't seem like the right thing because:
First, I lose packets that were already received at the time of the exception, but not yet "handled" by the application
Second, during the time between closing the current socket and creating a new one, the current port is not available to clients
And third, and most importantly (to my mind), such solution does not look "correct" and "elegant"
So, what the "best", "By the Book" solution you can suggest me for this case?
CodePudding user response:
You are receiving every port number. You only want to accept the port number for UDP, not TCP or other protocols. Not sure why you are getting a Keep-Alive. Is that in your code?
Here is how to get port number so you can return if data is not from your port numbers
UdpClient client = iar.AsyncState as UdpClient;
IPEndPoint ep = (IPEndPoint) client.Client.RemoteEndPoint;
int port = ep.Port ;
//return if not valid port number
EndPoint newClientEP = new IPEndPoint(IPAddress.Any, port);
client.Client.BeginReceiveFrom(this.byteData, 0, this.byteData.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, newClientEP);
CodePudding user response:
- In some cases sending UDP packets to currently crashed/rebooted/disconnected clients can caused exception with code 10052
- Just ignore the error and call BeginReceiveFrom again
Research Conclusions: This exception can thrown for both BeginReceiveFrom and EndReceiveFrom calls. Actually, this exception indicates a problem with SENDING data, not with RECEIVING. For EndReceiveFrom, the exception can be completely ignored In case of an exception in BeginReceiveFrom, it is necessary to call BeginReceiveFrom again
See the details on Experts-Exchange: UDP SocketException (code 10052) - The connection has been broken due to keep-alive activity