VB.NET本地TCP服务器倒计时器运行崩溃问题求助
解决TCP服务器非阻塞Socket操作异常问题
异常原因分析
你遇到的A non-blocking socket operation could not be completed immediately异常,本质是非阻塞Socket调用Receive时,当前没有数据可读取,系统无法立即完成操作导致的。你的Timer1持续轮询Socket接收,却未处理这种“无数据可用”的正常情况,反复触发异常最终引发程序崩溃。
具体解决方法
1. 正确处理非阻塞Socket的异常与返回值
如果坚持使用非阻塞Socket+Timer的模式,必须在捕获异常时区分“资源暂时不可用”和真正的错误:
try { byte[] buffer = new byte[1024]; int bytesReceived = clientSocket.Receive(buffer); if (bytesReceived > 0) { // 解析客户端发送的"分钟:秒"字符串 string timeInput = Encoding.UTF8.GetString(buffer, 0, bytesReceived).Trim(); // 更新倒计时初始值逻辑 } else { // 客户端主动断开,清理Socket资源 clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } } catch (SocketException ex) { // 忽略"无数据可接收"的非致命异常 if (ex.SocketErrorCode != SocketError.WouldBlock) { // 处理真正的Socket错误,比如连接中断 clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } }
2. 改用异步Socket接收替代Timer轮询
Timer轮询非阻塞Socket的方式效率低下且容易出错,推荐使用.NET异步Socket API,让系统在有数据时主动通知:
// 服务器启动逻辑 private void StartServer() { Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); serverSocket.Bind(new IPEndPoint(IPAddress.Loopback, 12345)); serverSocket.Listen(10); // 开始异步接受客户端连接 serverSocket.BeginAccept(OnClientConnected, serverSocket); } // 客户端连接回调 private void OnClientConnected(IAsyncResult ar) { Socket serverSocket = (Socket)ar.AsyncState; Socket clientSocket = serverSocket.EndAccept(ar); // 准备接收数据的状态对象 StateObject state = new StateObject { ClientSocket = clientSocket, Buffer = new byte[1024] }; // 开始异步接收数据 clientSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceived, state); // 继续监听新的客户端连接 serverSocket.BeginAccept(OnClientConnected, serverSocket); } // 数据接收回调 private void OnDataReceived(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket clientSocket = state.ClientSocket; try { int bytesRead = clientSocket.EndReceive(ar); if (bytesRead > 0) { string timeStr = Encoding.UTF8.GetString(state.Buffer, 0, bytesRead).Trim(); // 更新倒计时时间(注意跨线程更新UI需要用Invoke) this.Invoke(new Action(() => { /* 更新倒计时初始值 */ })); // 继续等待下一次数据接收 clientSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, OnDataReceived, state); } else { // 客户端断开连接 clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } } catch (Exception) { clientSocket.Shutdown(SocketShutdown.Both); clientSocket.Close(); } } // 用于保存异步操作状态的辅助类 private class StateObject { public Socket ClientSocket { get; set; } public byte[] Buffer { get; set; } }
3. 严格分离Timer职责
保留Timer2负责倒计时的UI更新逻辑,但必须将Socket接收逻辑从Timer1中完全移除,避免Timer线程与Socket操作的资源冲突。异步Socket模式无需Timer轮询,能更高效、稳定地处理客户端数据。
内容的提问来源于stack exchange,提问作者SirAleXbox
相关产品推荐
相关产品推荐

