Страницы

Поиск по вопросам

суббота, 6 июля 2019 г.

C# UDP Отправка сервера к клиенту байт выдает ошибку

Всем привет! Когда сервер отправляет байт данных на уже отключенный клиент то я получаю вот такое исключение:

Kак узнать клиент доступен ли? Как утсранить эту проблему или обоити ?
Искал в интернете, нашел пару похожих вопросов но у них другие проблемы в конце решил спросить тут.
Server:
byte[] buffer = new byte[1024]; IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 23000); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint EP = (EndPoint)sender;
int i; sock.Bind(ipep);
while (true) { try { i = sock.ReceiveFrom(buffer, ref EP); // ошибка появляется здесь } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.ReadKey(); break; }
// нажимаем на любую клаву чтобы получить ошибку Console.WriteLine("Нажмите любую клавишу чтобы отправить байт клиенту и получить ошибку"); Console.ReadKey(); sock.SendTo(buffer, i, SocketFlags.None, EP);
Client:
int serverPort = 23000; string hostName = "127.0.0.1"; byte[] buffer = new byte[1024];
EndPoint remote; IPEndPoint endPoint; Socket server;
endPoint = new IPEndPoint(IPAddress.Parse(hostName), serverPort); server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
remote = (EndPoint)sender;
buffer = Encoding.Unicode.GetBytes("me send"); server.SendTo(buffer, 0, buffer.Length, SocketFlags.None, endPoint);
// выходим из клиента чтобы сервер отправил отключенному клиенту;


Ответ

Socket.ReceiveFrom внутри использует функцию recvfrom. Она соотвественно может завершится с ошибкой WSAECONNRESET(код у неё 10054). В документации на функцию recvfrom указанано следующие описание ошибки WSAECONNRESET
The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
В кратце на русском: Если хост разорвет соединение и после этого будет вызыван send, то последующая операция чтения завершится с этой ошибкой.
Соответственно чтобы решить вашу проблему, нужно использовать примерно такой код:
static void Main(string[] args) { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
byte[] buffer = new byte[1024]; socket.Bind(new IPEndPoint(IPAddress.Any, 23000));
while (true) { var i = 0;
EndPoint clientPoint = new IPEndPoint(IPAddress.Any, 0); try { i = socket.ReceiveFrom(buffer, ref clientPoint); } catch (SocketException ex) when (ex.ErrorCode == 10054) { // ни чего не делаем идем дальше continue; } catch (Exception ex) { Console.WriteLine(ex.ToString()); break; }
socket.SendTo(buffer, i, SocketFlags.None, clientPoint); } } }
PS: Есть еще магическая константа SIO_UDP_CONNRESET, которая вроде убирает генерирование этой ошибки. Но я не уверен, что она влияет только на этот случай поэтому код приводить с ней не буду.

Комментариев нет:

Отправить комментарий