【问题标题】:TCPClient & TCPListener | Connection reset by peer crash c#TCPClient & TCPListener |对等崩溃 c# 重置连接
【发布时间】:2020-11-08 15:14:57
【问题描述】:

我有一个 TCP 侦听器(服务器)和一个 TCP 客户端(客户端)(在 2 个不同的程序中)。

如果我的客户端被强制停止(CTRL^C 或其他),则服务器程序会因此错误而停止:

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

我能做些什么来取消这个崩溃。我想做一个服务器来管理我的网络,如果一台计算机被强制断开,我不想从服务器崩溃。

我的代码:

服务器 -

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

客户 -

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

【问题讨论】:

    标签: c# .net crash tcpclient tcplistener


    【解决方案1】:

    似乎在客户端关闭连接时引发了异常,但在服务器端没有完全读取消息。在这种情况下,服务器正试图从关闭的套接字中获取信息。 如果我是你,我会捕获异常并正确地从池中删除连接。

    另外,我不清楚为什么在 Server.ThreadProc 方法中,您在循环的每次迭代中都调用 client.Close()。它可能会导致类似的问题。

    【讨论】:

    • 客户端断开连接时如何关闭套接字?
    • client.close() 是关闭套接字的有效方法。但是为什么要用 while(true) 循环来包装它呢?
    • 因为当客户端连接时,我将他放在一个线程中,并且在 while(true) 中我可以发送我想要的。但我不想打开连接、发送数据并关闭连接。我想打开连接,永远不要关闭他。
    • 好吧,我明白了。因此,您应该只捕获异常并(如果需要)执行一些清理逻辑。之后,客户端断开连接,相应线程可用于另一个连接
    • 好的,所以你应该捕获 IOException,在控制台中创建一些日志,然后从方法中返回。如果您想要多个连接 - 每个连接都将在单独的线程中处理,因此一个线程中的关闭连接不应影响另一个线程(如果您正确捕获所有异常)
    猜你喜欢
    • 2015-08-16
    • 2011-10-06
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2011-12-29
    • 2012-10-18
    • 2017-08-17
    • 2018-01-10
    相关资源
    最近更新 更多