C# UDP An existing connection was forcibly closed by the remote host(C# UDP 一个现有的连接被远程主机强行关闭)
问题描述
我正在为一个游戏创建一个服务器,该服务器使用异步方法通过 UDP
处理多个客户端,并且正在专门研究干净的断开连接逻辑.当客户端硬崩溃(他们的程序在没有适当的断开逻辑的情况下关闭)时,服务器上的 readCallback
会抛出 SocketException
I am creating a server for a game that handles multiple clients over UDP
using the asynchronous methods, and am specifically working on clean disconnect logic. When a client hard crashes (their program is closed without proper disconnect logic) the readCallback
on the server throws the SocketException
一个现有的连接被远程主机强行关闭
An existing connection was forcibly closed by the remote host
这是有道理的,但是当下次在 read
的循环中触发读取时,尽管回调中处理了异常,但它会崩溃.
which makes sense, however when the read is triggered the next time on the loop in read
it crashes despite the exception being handled in the callback.
private void connectedState()
{
while (connected)
{
//reset the trigger to non-signaled
readDone.Reset();
read(socket);
//block on reading data
readDone.WaitOne();
}
}
private void read(Socket sock)
{
// Creates an IpEndPoint to capture the identity of the sending host.
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint senderRemote = sender;
// Create the state object.
StateObject state = new StateObject();
state.workSocket = sock;
//crashes after an exception is caught within the callback
sock.BeginReceiveFrom(state.buffer, 0, StateObject.MESSAGE_SIZE, SocketFlags.None, ref senderRemote, new AsyncCallback(readCallback), state);
}
private void readCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket sock = state.workSocket;
EndPoint senderRemote = new IPEndPoint(IPAddress.Any, 0);
try
{
// Read data from the client socket.
int bytesRead = sock.EndReceiveFrom(ar, ref senderRemote);
if (bytesRead <= 0)
{
//handle disconnect logic
}
else
{
//handle the message received
}
}
catch (SocketException se)
{
Console.WriteLine(se.ToString());
}
// Signal the read thread to continue
readDone.Set();
}
抛出了两个异常,我认为其中一个被捕获了:
Two exceptions are thrown, one of which I believe is being caught:
抛出异常:System.dll 中的System.Net.Sockets.SocketException"System.Net.Sockets.SocketException (0x80004005):现有连接被远程主机强行关闭在 System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint)在 C:UserskayasDesktopPracticumSourceCardCatacombsCardCatacombsUtilitiesNetworkingUDPNetworkConnection.cs:line 424 中的 CardCatacombs.Utilities.Networking.UDPNetworkConnection.readCallback(IAsyncResult ar) 处
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint) at CardCatacombs.Utilities.Networking.UDPNetworkConnection.readCallback(IAsyncResult ar) in C:UserskayasDesktopPracticumSourceCardCatacombsCardCatacombsUtilitiesNetworkingUDPNetworkConnection.cs:line 424
抛出异常:System.dll 中的System.Net.Sockets.SocketException"System.Net.Sockets.SocketException (0x80004005):现有连接被远程主机强行关闭在 System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint endPointSnapshot, SocketAddress socketAddress, OverlappedAsyncResult asyncResult)
我希望能够干净地处理客户端崩溃并继续运行,因为还有其他客户端连接到服务器.
I would like to be able to cleanly handle a client crash and continue running since there are other clients connected to the server.
推荐答案
来自 这个论坛帖子,看来UDP socket也在接收ICMP消息,收到时抛出异常.如果端口不再监听(在硬崩溃之后),ICMP 消息会导致强制关闭"异常.
From this forum thread, it seems that the UDP socket is also receiving ICMP messages and throwing exceptions when they are received. If the port is no longer listening (after the hard crash), the ICMP message causes the 'forcibly closed' exception.
如果不需要,可以在创建 UdpClient 时使用以下代码禁用此异常,在上面的帖子中进行了解释:
If not wanted, this exception can be disabled using the following code when creating the UdpClient, explained in the above post:
public const int SIO_UDP_CONNRESET = -1744830452;
var client = new UdpClient(endpoint);
client.Client.IOControl(
(IOControlCode)SIO_UDP_CONNRESET,
new byte[] { 0, 0, 0, 0 },
null
);
对于 dotnet core 用户,因为这个Socket.IOControl";是windows特有的控制代码,其他平台不支持,会出现如下异常:
For dotnet core users, since this "Socket.IOControl" is a Windows-specific control code, other platforms are not supported, we will get the below exception:
未处理的异常.System.PlatformNotSupportedException:Socket.IOControl 处理特定于 Windows 的控制代码,在此平台上不受支持.
Unhandled exception. System.PlatformNotSupportedException: Socket.IOControl handles Windows-specific control codes and is not supported on this platform.
为了更好的兼容性,我们应该检查当前平台:
For better compatibility, we should check the current platform:
using System.Runtime.InterosServices;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
//...
}
这篇关于C# UDP 一个现有的连接被远程主机强行关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C# UDP 一个现有的连接被远程主机强行关闭
基础教程推荐
- rabbitmq 的 REST API 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- c# Math.Sqrt 实现 2022-01-01
- 如何激活MC67中的红灯 2022-01-01
- MS Visual Studio .NET 的替代品 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01