You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TCPListener客户端断开时抛异常致其他客户端崩溃问题排查

TCP客户端断开导致Listener崩溃问题修复

问题描述

当TCP客户端断开连接时,TCPListener抛出未处理异常;现有两个客户端每秒发送随机消息,关闭其中一个客户端后,Listener触发错误,导致另一个客户端也报错并关闭控制台应用。

异常信息

未处理的异常。System.IO.IOException: 
无法从传输连接读取数据: 
远程主机强迫关闭了一个现有的连接。
---> System.Net.Sockets.SocketException (10054): 远程主机强迫关闭了一个现有的连接。
在 System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 count)
--- 内部异常堆栈跟踪结束 ---
在 System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 count)
在 ConsoleApp2.Program.handle_connection(IAsyncResult result) 位置 C:\Users\ahmet\OneDrive\Desktop\new\ConsoleApp2\Program.cs:行 67
在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- 之前位置的堆栈跟踪结束 ---
在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- 之前位置的堆栈跟踪结束 ---
在 System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
在 System.Threading.ThreadPoolWorkQueue.Dispatch()
在 System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

TCP服务端代码

using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;

namespace ConsoleApp2 {
    class Program {
        TcpListener server = new TcpListener(IPAddress.Any, 13000);

        static void Main(string[] args) {
            
            try {
                Program main = new Program();
    
                main.server_start();
    
                Console.ReadLine();
                
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            }
            
    
        }
    
        private void server_start() {
            try {
                server.Start();
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            }
    
            Console.WriteLine("服务器已启动。等待连接...");
            accept_connection();
        }
    
        private void accept_connection() {
            try {
                server.BeginAcceptTcpClient(handle_connection, server);
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            }
        }
    
        private void handle_connection(IAsyncResult result) {
            try {
                Console.WriteLine("已连接...");
                accept_connection();
                TcpClient client = server.EndAcceptTcpClient(result);
    
                NetworkStream stream = client.GetStream();
                Byte[] bytes = new Byte[256];
                String data = null;
    
                int i;
    
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) {
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine("{0}", data);
                }
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            }
    
        }
        
    }

}

TCP客户端代码

using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Program
    {
        static TcpClient client = new TcpClient("127.0.0.1",13000);
        static List<string> messages = new List<string>();
        public static readonly object locker = new object();

        static void Main()
        {
            ThreadPool.QueueUserWorkItem(LoadMessages);
            Thread.Sleep(100);
            ThreadPool.QueueUserWorkItem(SendMessages);
            Console.ReadLine();
        }
    
        static void LoadMessages(object state)
        {
            lock (locker)
            {
                messages.Add("Java");
                messages.Add("C");
                messages.Add("C++");
                messages.Add("C#");
                messages.Add("Python");
                messages.Add("HTML");
                messages.Add("CSS");
                messages.Add("PHP");
                messages.Add("HELLO");
    
            }
        }
    
        static void SendMessages(object state)
        {
            while (true)
            {
                var random = new Random();
                string message = messages[random.Next(messages.Count)];
                
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);
                Console.WriteLine("消息已发送");
                Thread.Sleep(1000);
            }
        }
    }

}

尝试过的方法

尝试返回false,但提示BeginAcceptTcpClient()需要void类型。

解决方案

问题核心是handle_connection方法未捕获IOException,客户端强制断开时stream.Read抛出该异常,未处理导致程序崩溃;同时未正确关闭连接造成资源泄漏。修改后的服务端代码如下:

using System;
using System.Threading;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Collections.Generic;

namespace ConsoleApp2 {
    class Program {
        TcpListener server = new TcpListener(IPAddress.Any, 13000);

        static void Main(string[] args) {
            
            try {
                Program main = new Program();
    
                main.server_start();
    
                Console.ReadLine();
                
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            } catch (Exception e) {
                Console.WriteLine("未处理异常: {0}", e);
            }
            
    
        }
    
        private void server_start() {
            try {
                server.Start();
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            } catch (Exception e) {
                Console.WriteLine("启动服务器失败: {0}", e);
            }
    
            Console.WriteLine("服务器已启动。等待连接...");
            accept_connection();
        }
    
        private void accept_connection() {
            try {
                server.BeginAcceptTcpClient(handle_connection, server);
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("SocketException: {0}", e);
            } catch (Exception e) {
                Console.WriteLine("接受连接失败: {0}", e);
            }
        }
    
        private void handle_connection(IAsyncResult result) {
            TcpClient client = null;
            NetworkStream stream = null;
            try {
                Console.WriteLine("已连接...");
                // 提前监听新连接,避免阻塞
                accept_connection();
                
                client = server.EndAcceptTcpClient(result);
                stream = client.GetStream();
                Byte[] bytes = new Byte[256];
                String data = null;
    
                int i;
    
                while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) {
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                    Console.WriteLine("收到消息: {0}", data);
                }
            } catch (ArgumentNullException e) {
                Console.WriteLine("ArgumentNullException: {0}", e);
            } catch (SocketException e) {
                Console.WriteLine("Socket异常(客户端断开): {0}", e);
            } catch (IOException e) {
                Console.WriteLine("IO异常(客户端断开): {0}", e);
            } catch (Exception e) {
                Console.WriteLine("处理连接时出错: {0}", e);
            } finally {
                // 确保资源被正确释放
                stream?.Close();
                client?.Close();
                Console.WriteLine("连接已关闭");
            }
        }
        
    }

}

修改点说明

  1. 添加IOException捕获:直接捕获客户端断开时抛出的IOException,避免未处理异常导致程序崩溃。
  2. 资源释放:使用finally块确保TcpClient和NetworkStream被正确关闭,防止资源泄漏。
  3. 提前监听新连接:在获取客户端连接前调用accept_connection(),确保服务器不会错过新的连接请求。
  4. 全局异常捕获:在Main和server_start中添加通用Exception捕获,处理其他未预见的错误。

修改后,单个客户端断开只会触发对应连接的异常处理,不会影响服务器整体运行,其他客户端可正常通信。

内容的提问来源于stack exchange,提问作者Saul4Goodman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 17:38:11