C#中UdpClient.Receive报‘远程主机强制关闭连接’异常求助
解决UDP查询游戏服务器时的“远程主机强制关闭现有连接”异常
首先咱们得先搞清楚这个异常的根源:UDP本身是无连接协议,但你调用了udpClient.Connect(IP, Port),这会让你的UDP客户端绑定到指定的远程端点,相当于在客户端层面做了一个“虚拟连接”。当目标服务器下线或者拒绝响应时,系统就会返回这个强制关闭连接的错误——毕竟这个虚拟连接已经失效了。
下面给你几个具体的解决思路和代码示例:
1. 移除Connect()调用,改用无连接的UDP通信
既然UDP不需要提前建立连接,直接发送和接收数据包就好,这样能避免因虚拟连接失效触发的异常。修改后的QueryServer方法可以这样写:
private void QueryServer(IPAddress IP, int Port) { // 每次查询创建新的UdpClient实例,避免复用带来的状态问题 using (UdpClient udpClient = new UdpClient()) { try { // 设置接收超时,避免长时间阻塞 udpClient.Client.ReceiveTimeout = 3000; // 3秒超时 IPEndPoint remoteEndPoint = new IPEndPoint(IP, Port); // 直接发送数据包,不需要提前Connect Byte[] sendBytes = Encoding.ASCII.GetBytes("你的查询指令"); udpClient.Send(sendBytes, sendBytes.Length, remoteEndPoint); // 接收响应 Byte[] receiveBytes = udpClient.Receive(ref remoteEndPoint); string response = Encoding.ASCII.GetString(receiveBytes); // 处理响应,更新ListView(注意跨线程操作UI) UpdateListView(IP, Port, "在线", response); } catch (SocketException ex) { // 捕获超时或连接相关异常,标记服务器为下线 if (ex.SocketErrorCode == SocketError.TimedOut || ex.SocketErrorCode == SocketError.ConnectionReset) { UpdateListView(IP, Port, "离线", "无响应"); } else { // 处理其他异常 Console.WriteLine($"查询服务器{IP}:{Port}时出错:{ex.Message}"); } } } }
2. 针对异常做针对性处理(如果必须保留Connect())
如果你因为某些原因必须使用Connect(),那一定要在代码中捕获这个特定的SocketException,并将其视为服务器离线的信号:
private void QueryServer(IPAddress IP, int Port) { using (UdpClient udpClient = new UdpClient()) { try { udpClient.Connect(IP, Port); udpClient.Client.ReceiveTimeout = 3000; Byte[] sendBytes = Encoding.ASCII.GetBytes("你的查询指令"); udpClient.Send(sendBytes, sendBytes.Length); Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); // 处理在线逻辑 } catch (SocketException ex) { // 匹配远程主机强制关闭连接的错误码 if (ex.SocketErrorCode == SocketError.ConnectionReset) { // 标记服务器为离线,更新ListView UpdateServerStatus(IP, Port, false); } else { // 处理其他错误 throw; } } } }
3. 额外的最佳实践
- 避免复用UdpClient实例:每个查询用新的实例,避免之前的连接状态干扰后续操作。
- 跨线程更新UI:如果
QueryServer是在后台线程执行的,更新ListView时一定要用Invoke或BeginInvoke,避免UI线程异常。 - 批量查询时加延迟:如果一次性查询多个服务器,不要同时发送所有请求,适当加小延迟,避免被目标网络限制。
内容的提问来源于stack exchange,提问作者LEEFFM
相关产品推荐
相关产品推荐

