C# 异步 UDP 侦听器 SocketException

发布于 2024-10-20 12:35:47 字数 1892 浏览 7 评论 0原文

我有一个非常简单的异步 UDP 侦听器,设置为服务,并且它已经工作了一段时间,但它最近因 SocketException 现有连接被远程主机强制关闭而崩溃。我有三个问题:

  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() 行引发异常。

I have a pretty simple Asynchronous UDP listener, setup as a service, and it's been working quite well for awhile now, but it recently crashed on a SocketException An existing connection was forcibly closed by the remote host. I have three questions:

  1. What's causing this? (I didn't think UDP sockets had a connection)
  2. How can I duplicate it, for testing purposes?
  3. How can I cleanly handle the exception, so everything will continue to work?

My code looks something like the following:

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.
    }
}

The exception is being thrown at the recvSock.EndReceiveFrom() line.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ま柒月 2024-10-27 12:35:47

来自此论坛帖子,看来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
);

From this forum thread, it seems that the UDP socket is also receiving ICMP messages and throwing exceptions when they are received. Maybe this is great for low level status updates, but I found it annoying.

First, define the magic number

public const int SIO_UDP_CONNRESET = -1744830452;

Then set the low level io control to ignore these messages:

var client = new UdpClient(endpoint);
client.Client.IOControl(
    (IOControlCode)SIO_UDP_CONNRESET, 
    new byte[] { 0, 0, 0, 0 }, 
    null
);
刘备忘录 2024-10-27 12:35:47

如果数据包以某种方式被截断或未完全传送,我已经看到 UDP 的错误。至少,我认为就是这样。我从来没能可靠地复制它。

我建议您捕获 SocketException,记录它(如果您愿意),然后处理该套接字。然后再次调用 Starter

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

I've seen that error with UDP if a packet is somehow truncated or otherwise not completely delivered. At least, I think that's what happens. I've never been able to duplicate it reliably.

I would suggest that you catch the SocketException, log it (if you want), and then dispose of that socket. Then call Starter again:

catch (SocketException)
{
    // log error
    udpSock.Close();
    Starter();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文