Hello. Unfortunately, I don’t know how to raise old topics, in particular, this SocketException 10054 . I am writing a test client server, learning to work with UDP. I had a similar problem as the link above and the interest is more theoretical than practical. But I will try to explain it in more detail. There is an open UDP channel on the server. It accepts messages from any address via BeginReceiveFrom / EndReceiveFrom. There is a list of addresses - the usual List of IPEndPoint. This list is only updated, that is, if the client application or connection was closed, the address is not removed from the list.
When someone sends a message to a server UDP socket, the server tries to send it to all recipients from the list. Naturally, if the addressee does not exist, then a sending error should pop up, but instead, an error occurs in the EndReceiveCallback method, namely on the line with _socket.BeginReceiveFrom (...), after which the socket is closed.
Here is the code for clarity:
private void OnReceiveCallback(IAsyncResult ar) { EndPoint ep = _remoteEndPoint; int rLenght = 0; try{ if (_isClosed == 0) { rLenght = _socket.EndReceiveFrom(ar, ref ep); } } catch (Exception ex) { CatchedException(ex); } try { if (rLenght > 0){ byte[] receive = _readBuffer; byte[] pack = NetProtocol.GetPacket(ref receive); if (pack != null) { ReceiveAction?.Invoke(this, pack); } } if (_isClosed == 0){ ep = _remoteEndPoint; _socket.BeginReceiveFrom(_readBuffer, 0, _readBufferSize, SocketFlags.None, ref ep, OnReceiveCallback, ep); } } catch (Exception ex) { CatchedException(ex); } } public override void Send(byte[] data, object sendParam = null) { IPEndPoint ep = null; try{ if (!_remoteEndPoint.Equals(Any)){ ep = _remoteEndPoint; } else{ ep = sendParam as IPEndPoint; } if (ep != null){ if (_isClosed == 0){ _socket.BeginSendTo(data, 0, data.Length, SocketFlags.None, ep, OnSendCallbackTo, null); } } } catch (Exception ex){ SocketException sex = ex as SocketException; if (sex != null) { NetLogger.Log("SEX " + sex.ErrorCode + ", " + sex); } else { NetLogger.Log("SOCKET: " + ex); return; } } }
In the CatchedException () function, the socket is closed if the error was of type SocketException, but as can be seen from the code, the function is called only from the res method. In the send method, the error is simply written to the log and should not break anything. Actually the question is why the error is caught in the Receive method, and not in the Send?
Clarification A socket breaks a connection in any case, even if instead of manually closing on error, it is easy to log.
What I tried additionally:
- if the address is removed from the list before closing the client, everything works fine.
- I thought there might be some kind of magic dependence on closing the socket of a previously connected client, but if you enter a fake address before starting, the error is reproduced again.
Clarification 2 By creating two sockets on the server side (a clean receiver and a clean sender), we managed to solve the disconnect problem. On the client, respectively, the same 2 addresses are set - for sending to the server's Receive channel, and receiving only from the sender channel. But I consider this solution to be a crutch and leave the question open , because in this situation even the native dot-UDP UDPClient falls away from this problem and in fact the UDP socket operation has an uncontrollable dependence on the delivery address.
Естественно, что если адресат не существует, то должна выскакивать ошибка отправки,
no. UDP is sending without confirmation. And the sending party does not know whether the addressee received the message or not (if he does not deign to inform about it himself). - KoVadim