Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# UDP An existing connection was forcibly closed by the remote host

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

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:


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:\Users\kayas\Desktop\Practicum\Source\CardCatacombs\CardCatacombs\Utilities\Networking\UDPNetworkConnection.cs:line 424

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.

like image 506
Rhea Lauzon Avatar asked Jul 04 '16 20:07

Rhea Lauzon


People also ask

What is C in simple words?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C or C++ same?

While C and C++ may sound similar, their features and usage differ. C is a procedural programming language that support objects and classes. On the other hand C++ is an enhanced version of C programming with object-oriented programming support.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

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.

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
);

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:

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))
{
   //...
}
like image 50
jamesw6811 Avatar answered Sep 16 '22 19:09

jamesw6811