Search code examples
c#.netcrashtcpclienttcplistener

TCPClient & TCPListener | Connection reset by peer crash c#


I have an TCP Listener (server) and a TCP Client (client) (in 2 different programs).

If my client is forcely stopped (CTRL^C or other) the server program is stopped with this error :

Unhandled Exception:
System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.Receive (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags) [0x0001a] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
  at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x000b4] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
   --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x0010f] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
  at loginserver.Program.ThreadProc (System.Object obj) [0x00090] in <a4c14a5640d24e26ae5e0c9bc660a224>:0
  at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x0000e] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x0008d] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x0002a] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00096] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer. ---> System.Net.Sockets.SocketException: Connection reset by peer
  at System.Net.Sockets.Socket.Receive (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags) [0x0001a] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
  at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x000b4] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
   --- End of inner exception stack trace ---
  at System.Net.Sockets.NetworkStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x0010f] in <a9a08e39ba304bd0a84c49bd158dfc02>:0
  at loginserver.Program.ThreadProc (System.Object obj) [0x00090] in <a4c14a5640d24e26ae5e0c9bc660a224>:0
  at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x0000e] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x0008d] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x0002a] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00096] in <d0e12f672b88444ab4b6d9b2ecf20142>:0
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <d0e12f672b88444ab4b6d9b2ecf20142>:0

What can i do to cancel this crash. I want to make a server to manage my network, and if a computer is forcely deconnected, i don't want to a crash from the server.

My code :

Server -

class Program
    {
        TcpListener server = null;

        static void Main(string[] args)
        {
            TcpListener server = null;
            try
            {
                string ports = args[1];
                Int32 port = Int32.Parse(ports);
                IPAddress localAddr = IPAddress.Parse(args[0]);
                server = new TcpListener(localAddr, port);
                server.Start();
                TcpClient client;
                while (true)
                {
                    client = server.AcceptTcpClient();
                    ThreadPool.QueueUserWorkItem(ThreadProc, client);
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            Console.WriteLine("\nHit enter to continue...");
            Console.Read();
        }
        private static void ThreadProc(object obj)
        {
            var client = (TcpClient)obj;
            Byte[] bytes = new Byte[256];
            String data = null;
            while (true)
            {
                Console.WriteLine("Waiting for a connection... ");
                var networkStream = client.GetStream();
                var pi = networkStream.GetType().GetProperty("Socket", BindingFlags.NonPublic | BindingFlags.Instance);
                var socketIp = ((Socket)pi.GetValue(networkStream, null)).RemoteEndPoint.ToString();
                Console.WriteLine("Connected -> " + socketIp);
                data = null;
                NetworkStream stream = client.GetStream();
                int i;
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine("Received: {0}", data );
                }
                client.Close();
            }
        }
    }

Client -

class Program
    {
        static void Main(string[] args)
        {
            while (true)
            { 
                string IP = "localhost";
                int port = 13000;
                TcpClient client = new TcpClient();
                try
                { 
                    client.Connect(IP, port);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error : " + ex.Message);
                }

                if (client.Connected)
                {
                    NetworkStream stream = client.GetStream();
                    Console.WriteLine("Connected !");
                    string tosend = "Hey" !;
                    Console.WriteLine("Send: " + tosend);
                    Byte[] data = System.Text.Encoding.ASCII.GetBytes(tosend);
                    stream.Write(data, 0, data.Length);
                    while (client.Connected)
                    {
                        Thread.Sleep(1000);
                    }
                    stream.Close();
                    client.Close();
                    Thread.Sleep(10000);
                }
            }
        }
    }

Solution

  • It looks like the exception is raised when the connection is closed on the client, but the message isn`t fully read on the server-side. In that case, the server is trying to get the information from the closed socket. If I were you, I would just catch the exception and remove the connection from the pool properly.

    Also, it is not clear to me why in Server.ThreadProc method you are calling client.Close() in every iteration of the loop. It may cause similar problems.