9

私は非常に単純な非同期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()行でスローされています。

4

2 に答える 2

19

このフォーラム スレッドから、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
);
于 2012-02-03T08:04:00.353 に答える
2

パケットが何らかの形で切り捨てられたり、完全に配信されなかったりした場合に、UDP でそのエラーが発生するのを見てきました。少なくとも、私はそれが起こると思います。確実に複製することはできませんでした。

をキャッチしSocketException、(必要に応じて)ログに記録してから、そのソケットを破棄することをお勧めします。次に、Starterもう一度呼び出します。

catch (SocketException)
{
    // log error
    udpSock.Close();
    Starter();
}
于 2011-03-04T20:52:29.080 に答える