#c_sharp #сеть #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); // выходим из клиента чтобы сервер отправил отключенному клиенту;
Ответы
Ответ 1
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, которая вроде убирает генерирование этой ошибки. Но я не уверен, что она влияет только на этот случай поэтому код приводить с ней не буду.
Комментариев нет:
Отправить комментарий