.NET Framework双端口监听异常:Task.WhenAny阻塞问题求助
问题分析与解决方案
这个问题的核心原因是在.NET Framework中,TcpListener的异步接受方法(比如AcceptSocketAsync)不支持同时存在多个挂起的接受操作,而你的代码每次循环都会给所有Listener重新发起一次接受请求,导致未完成的旧请求和新请求冲突,最终使得后续的端口连接无响应。而.NET Core对TcpListener的实现做了优化,允许这种模式,所以在Core下能正常工作。
你的代码哪里出了问题?
看你的AcceptAnyConnection方法,每次调用时都会给每个TcpListener创建一个新的AcceptConnection任务(也就是发起一次新的AcceptSocketAsync请求)。当第一个端口(比如6060)被连接后,另一个Listener(6061)的AcceptSocketAsync任务其实还在后台等待连接,但下一次循环你又给6061的Listener发起了新的AcceptSocketAsync请求——在.NET Framework里,同一个TcpListener实例同时只能有一个挂起的接受操作,新的请求会干扰甚至覆盖旧的,导致后续对6061端口的连接无法被正确处理。
修复后的代码示例
正确的做法是为每个TcpListener单独启动一个持续的接受循环,让每个Listener独立处理自己端口的连接,避免请求冲突:
static void Main(string[] args) { IPAddress hostIP = Dns.GetHostAddresses("127.0.0.1")[0]; List<TcpListener> listeners = new List<TcpListener>() { new TcpListener(hostIP, 6060), new TcpListener(hostIP, 6061) }; try { foreach (TcpListener listener in listeners) { listener.Start(); // 为每个Listener启动独立的接受循环 _ = HandleListenerAsync(listener); } // 保持主线程运行,避免程序直接退出 Console.WriteLine("服务器已启动,按任意键退出..."); Console.ReadKey(); } finally { foreach (TcpListener listener in listeners) { listener.Stop(); } } } private static async Task HandleListenerAsync(TcpListener listener) { try { while (true) { Socket socket = await listener.AcceptSocketAsync(); // 后台处理连接,不阻塞当前Listener的接受循环 _ = HandleConnectionAsync(socket); } } catch (SocketException) { // Listener被Stop时会抛出异常,这里可以做日志或忽略 Console.WriteLine($"Listener {listener.LocalEndpoint} 已停止"); } } private static async Task HandleConnectionAsync(Socket socket) { try { using (NetworkStream stream = new NetworkStream(socket)) { byte[] bytes = Encoding.UTF8.GetBytes(DateTime.Now.ToString()); await stream.WriteAsync(bytes, 0, bytes.Length); } } catch (Exception ex) { Console.WriteLine($"处理连接时出错: {ex.Message}"); } finally { socket.Close(); } }
关键修改点说明
- 独立的Listener循环:每个
TcpListener有自己的HandleListenerAsync循环,持续监听自身端口,不会和其他Listener的接受操作冲突。 - 后台处理连接:用
_ = HandleConnectionAsync(socket)让连接处理在后台异步执行,避免阻塞当前Listener的接受流程,保证新连接能被及时响应。 - 主线程保持存活:通过
Console.ReadKey()让主线程持续运行,防止程序启动后直接退出。 - 异常处理:添加了针对Listener停止和连接处理的异常捕获,让程序更健壮。
这种模式在.NET Framework和.NET Core下都能稳定工作,彻底解决了端口无响应的问题。
内容的提问来源于stack exchange,提问作者Archie
相关产品推荐
相关产品推荐

