C # Async UDP слушатель SocketException - PullRequest
7 голосов
/ 04 марта 2011

У меня довольно простой асинхронный прослушиватель UDP, настроенный как служба, и он работает довольно хорошо уже некоторое время, но недавно он завис на SocketException An existing connection was forcibly closed by the remote host.У меня три вопроса:

  1. Что вызывает это?(Я не думал, что у UDP-сокетов было соединение)
  2. Как мне продублировать его для целей тестирования?
  3. Как я могу чисто обработать исключение, чтобы все продолжало работать?

Мой код выглядит примерно так:

private Socket udpSock;
private byte[] buffer;
public void Starter(){
    //Setup the socket and message buffer
    udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    udpSock.Bind(new IPEndPoint(IPAddress.Any, 12345));
    buffer = new byte[1024];

    //Start listening for a new message.
    EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
    udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);
}

private void DoReceiveFrom(IAsyncResult iar){
    try{
        //Get the received message.
        Socket recvSock = (Socket)iar.AsyncState;
        EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
        int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
        byte[] localMsg = new byte[msgLen];
        Array.Copy(buffer, localMsg, msgLen);

        //Start listening for a new message.
        EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
        udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);

        //Handle the received message
        Console.WriteLine("Recieved {0} bytes from {1}:{2}",
                          msgLen,
                          ((IPEndPoint)clientEP).Address,
                          ((IPEndPoint)clientEP).Port);
        //Do other, more interesting, things with the received message.
    } catch (ObjectDisposedException){
        //expected termination exception on a closed socket.
        // ...I'm open to suggestions on a better way of doing this.
    }
}

Исключение выдается в строке recvSock.EndReceiveFrom ().

Ответы [ 2 ]

15 голосов
/ 03 февраля 2012

Из этой ветки форума кажется, что UDP-сокет также получает ICMP-сообщения и выдает исключения при их получении.Может быть, это хорошо для обновлений статуса низкого уровня, но я нахожу это раздражающим.

Сначала определите магическое число

public const int SIO_UDP_CONNRESET = -1744830452;

Затем установите элемент управления низкого уровня io, чтобы игнорировать эти сообщения:

var client = new UdpClient(endpoint);
client.Client.IOControl(
    (IOControlCode)SIO_UDP_CONNRESET, 
    new byte[] { 0, 0, 0, 0 }, 
    null
);
2 голосов
/ 04 марта 2011

Я видел эту ошибку с UDP, если пакет каким-то образом обрезан или иным образом не полностью доставлен.По крайней мере, я думаю вот что происходит.Мне никогда не удавалось надежно воспроизвести его.

Я бы посоветовал вам перехватить SocketException, записать его (если хотите), а затем утилизировать этот сокет.Затем снова позвоните Starter:

catch (SocketException)
{
    // log error
    udpSock.Close();
    Starter();
}
...