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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:35:20