You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UDP客户端RecData方法接收数据时为何未抛出预期异常?

问题分析与解决

首先咱们拆解下你的问题:你明明看到Receive方法触发了“An existing connection was forcibly closed by the remote host”异常,但RecData()方法却没有向外抛出这个异常,反而直接返回了null——这其实是你的代码逻辑+UDP的特性共同导致的,咱们一步步说清楚:

为什么UDP会出现“连接被强制关闭”的异常?

UDP本身是无连接协议,正常情况下不会出现类似TCP的“连接关闭”类错误,但你的代码里调用了client.Connect(toconnectto, 25565),这会把UdpClient切换到虚拟连接状态:

  • 此时这个UdpClient只能和指定的IP/端口通信
  • 如果远程主机主动关闭了对应端口,或者返回了ICMP“端口不可达”的消息,系统内核会把这个错误绑定到这个已连接的UdpClient上,当你调用Receive时就会触发SocketException,也就是你看到的那条错误信息。

为什么你感觉“RecData()没抛出异常”?

看你的RecData方法里的异常处理逻辑:

try
{
    IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, 25565);
    byte[] data = client.Receive(ref iPEndPoint);
    return ASCIIEncoding.ASCII.GetString(data);
}
catch(Exception e)
{
    return null;
}

你的catch块捕获了所有类型的异常,并且没有做任何日志输出、异常重抛的操作,只是直接返回null。也就是说,异常确实发生了,但被你的代码内部“吞”掉了,外部调用者只能拿到null,看不到异常的具体信息——这就是你疑惑的核心原因。

另外你提到client.Available初始值为1,抛出异常后变为0:这是因为系统把收到的ICMP错误当成了“待处理数据”,所以Available显示为1,但当你调用Receive时,系统会把这个错误转化为异常抛出,同时清空Available的计数。

修复建议

针对你的多人射击游戏场景,给你几个可行的调整方向:

  • 如果不需要固定远程端点:去掉client.Connect()调用,使用无连接的UDP通信。这样UdpClient可以和任意端点交互,也不会触发这类“连接关闭”的异常(但仍可能遇到其他网络相关的SocketException)。
  • 保留虚拟连接,但不要吞掉异常:修改catch块,至少记录异常信息方便排查问题,比如:
    catch(SocketException e)
    {
        // 可以写入日志或者输出到控制台,方便调试
        Console.WriteLine($"UDP接收出错: {e.Message}, 错误码: {e.ErrorCode}");
        return null;
    }
    catch(Exception e)
    {
        // 处理其他非网络类异常
        return null;
    }
    
  • 不要依赖client.Available判断:这个属性的状态可能在你检查和调用Receive之间发生变化,比如刚检查完Available>0,就收到了错误消息,导致Receive抛出异常。更稳妥的方式是直接尝试接收,依赖异常处理来处理错误情况。

内容的提问来源于stack exchange,提问作者Michael Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:43:00