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

196
10 ноября 2018, 14:00

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

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

READ ALSO
Удаление объекта из БД и combobox WPF

Удаление объекта из БД и combobox WPF

Ситуация следующая: у меня есть База данных(БД) Department у этой БД два поля id и DepNameЗадача: по нажатию кнопки "Удалить" - удалить объект из БД Department...

154
Выводить исключения в stderr

Выводить исключения в stderr

Подскажите пожалуйстаИсключения (exceptions) в C# по умолчанию выводятся в stdout, мне нужно их выводить в stderr (чтобы потом обработать только поток...

170
Есть ли скрипт для скачивание с google play?

Есть ли скрипт для скачивание с google play?

Как можно скачивать приложение с гугл плей через php скрипт? это нужно что бы отдавать готовый файл пользователям

151
Laravel подстановка маршрута

Laravel подстановка маршрута

Как в Laravel использовать подстановку маршрутаНапример:$route['category/(:any)/page/(:num)'] = '/category/page/$1/$2';

182