9

我有一个非常简单的异步 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() 行抛出异常。

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 回答