我正在使用异步方法为UDP
处理多个客户端的游戏创建一个服务器,并专门研究干净的断开逻辑。当客户端硬崩溃(他们的程序没有正确的断开逻辑而关闭)时,服务器上的readCallback
会抛出SocketException
远程主机强行关闭现有连接
这是有道理的,但是当下次在read
的循环中触发读取时,它会崩溃,尽管在回调中处理了异常。
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();
}
抛出两个例外,我相信其中一个被抓住了:
抛出异常:&#39; System.Net.Sockets.SocketException&#39;在System.dll中 System.Net.Sockets.SocketException(0x80004005):远程主机强制关闭现有连接 在System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult,EndPoint&amp; endPoint) 在CardCatacombs.Utilities.Networking.UDPNetworkConnection.readCallback(IAsyncResult ar)中的C:\ Users \ kayas \ Desktop \ Practicum \ Source \ CardCatacombs \ CardCatacombs \ Utilities \ Networking \ UDPNetworkConnection.cs:line 424
抛出异常:&#39; System.Net.Sockets.SocketException&#39;在System.dll中 System.Net.Sockets.SocketException(0x80004005):远程主机强制关闭现有连接 at System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte [] buffer,Int32 offset,Int32 size,SocketFlags socketFlags,EndPoint endPointSnapshot,SocketAddress socketAddress,OverlappedAsyncResult asyncResult)
我希望能够干净地处理客户端崩溃并继续运行,因为还有其他客户端连接到服务器。
答案 0 :(得分:10)
从this forum thread开始,UDP套接字似乎也在接收ICMP消息并抛出异常。如果端口不再侦听(在硬崩溃后),ICMP消息将导致“强制关闭”异常。
如果不需要,可以在创建UdpClient时使用以下代码禁用此异常,如上文所述:
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
);