Lately I've been experimenting with creating a multiplayer game. In the game each client sends a UDP datagram to the server every time he moves. Then every X seconds the server sends to all the clients the current state of the game so each client can render all of the other clients.
However when implementing the server I ran into a complication upon receiving datagrams from the clients.
If, lets say, Client A starts sending UDP datagrams to the server and then crashes for whatever reason. If the server tries to send a message back to the client, since no port is listening on the UDP port on the client's side, his machine will respond with an ICMP packet that contains a ConnectionReset. However, when receiving such packet, I don't have any way through code to know from which remote end point this was received.
Moreover, I've read that the best way to deal with this scenario is simply to close the UDP socket on which this was received (but I obviously don't want to close it, so the server can continue running).
Code to reproduce the scenario:
IPEndPoint serverEndp = new IPEndPoint(IPAddress.Loopback, 8080);
UdpClient server = new UdpClient(serverEndp);
// New client
UdpClient client = new UdpClient();
client.Send(new byte[] { 1, 2, 3 }, 3, serverEndp);
// Simulating that the client has crashed
client.Close();
client.Dispose();
IPEndPoint clientEndPoint = null;
// Server received a datagram from a client which has crashed.
server.Receive(ref clientEndPoint);
// Server doesn't know the client has crashed and tries to send him data back.
server.Send(new byte[] { 4, 5, 6 }, 3, clientEndPoint);
try
{
// The client's machine sends the server an ICMP ConnectionReset datagram.
// When this datagram is received this will throw an exception.
server.Receive(ref clientEndPoint);
}
catch (SocketException se)
{
Console.WriteLine(SocketError.ConnectionReset == se.SocketErrorCode); // True
Console.WriteLine("How to deal with this?");
}
I have several questions:
- Should I change my approach to have an extra TCP connection and then determine by that when the client has crashed?
- What is the best way to deal with the above scenario?