C# Async UDP прослушиватель SocketException

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

  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 ответов


С эта ветка форума, кажется, что сокет 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
);

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

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

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