【问题标题】:How to recover gracefully from a C# udp socket exception如何从 C# udp 套接字异常中优雅地恢复
【发布时间】:2011-02-06 11:41:28
【问题描述】:

上下文:我正在将 linux perl 应用程序移植到 C#,服务器侦听 udp 端口​​并通过单个 udp 套接字与远程客户端维护多个并发对话。在测试期间,我向 udp 服务器发送大量数据包,随机重启客户端以观察服务器注册新连接。问题是这样的:当我杀死一个 udp 客户端时,服务器上可能仍有发往该客户端的数据。当服务器尝试发送此数据时,它会收到一条 icmp“无可用服务”消息,因此套接字上会发生异常。

我无法重用此套接字,当我尝试将 C# 异步处理程序与套接字关联时,它会抱怨异常,因此我必须关闭并重新打开服务器端口上的 udp 套接字。这是解决这个问题的唯一方法吗?肯定有某种方法可以“修复” udp 套接字,因为从技术上讲,UDP 套接字不应该知道远程套接字的状态?

任何帮助或指针将不胜感激。谢谢。

【问题讨论】:

    标签: c# sockets udp


    【解决方案1】:

    我认为你说得对:'服务器不应该知道'。如果您将 UDP 数据包发送到某个可能打开或未打开的 IP/端口,则服务器无法知道它是否到达了目的地。

    服务器知道的唯一方法是让客户端发回一个 ACK​​。 (此外,客户端和服务器都必须有重新发送机制,以防丢失包裹)。

    很明显,您的代码(或使用 .Net udp 实现)中发生了其他事情

    编辑:

    在 Nikolai 发表评论后,我查看了文档。确实,.Net 在使用 UDP 时对于“已连接”或“无连接”是有区别的。

    如果你使用这样的代码:

    UdpClient udpClient = new UdpClient(11000); //sourceport
    try{
         udpClient.Connect("www.contoso.com", 11000); //'connect' to destmachine and port
         // Sends a message to the host to which you have connected.
         Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");
         udpClient.Send(sendBytes, sendBytes.Length);
    

    那么显然你已经“连接”了

    但是,如果你使用这样的代码:

         UdpClient udpClientB = new UdpClient();
         udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);
    

    然后您可以发送给您选择的任何人而无需“连接”。

    我不确定您的代码是什么样的,但可能值得检查一下您是否使用了不假定“连接”的正确命令集

    【讨论】:

    • 好吧,从技术上讲,如果远程端发送回一个 icmp“目标不可达”信号,网络堆栈就会知道一个关闭的 udp 端口​​,某些实现会这样做。也许我会尝试暂时阻止 icmp,我会看看我是否得到相同的异常......
    • @gearoid 即使那样,发送另一个包也应该可以工作,因为套接字无法知道端口是否已备份
    • 已连接未连接 UDP 套接字之间存在区别。对于前者,内核会知道将 ICMP 错误导向哪个应用程序;对于后者它不会,所以错误没有传递。这一切都归结为套接字端口分配。然后我不知道它在 .NET 中是如何工作的。
    • @reiner:感谢提供示例代码,我会在了解更多信息后发布更多详细信息......
    • 在我的代码中,套接字是一个服务器套接字,它正在监听。异常发生在接收操作期间。据我所知,连接和无连接 udp 套接字之间的区别仅出现在客户端的上下文中。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 2012-10-02
    • 2012-10-29
    • 2011-08-07
    • 1970-01-01
    相关资源
    最近更新 更多