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

使用std::thread处理TCP socket收发数据触发运行时错误如何解决?

问题原因与解决方案

报错根因

你遇到的运行时错误由两个核心问题共同导致:

  • std::thread对象未正确处理:C标准规定,若std::thread实例在析构时仍处于可连接(joinable)状态,会直接调用std::terminate终止程序,这是触发VC运行时错误的直接原因。
  • 资源生命周期不匹配:main函数创建线程后直接返回,栈上的TCPConnection实例会被立刻析构,析构函数会关闭socket、清理Winsock资源,此时仍在运行的接收线程访问已失效的socket会触发未定义行为。

解决思路

你需要同时处理线程状态和资源生命周期,既避免线程阻塞主逻辑,又保证资源在线程运行期间有效:

  1. 对不需要后续手动控制生命周期的线程,调用detach()将线程执行逻辑和std::thread对象解绑,避免对象析构时触发终止逻辑。
  2. 新增线程安全的退出标记,控制收发线程的退出时机,避免死循环访问失效资源。
  3. 保证TCPConnection实例的生命周期覆盖所有收发线程的运行周期,不要在线程还在运行时销毁连接实例。

修改后的代码示例

#include <atomic>

// 线程安全的全局运行标记,也可封装到TCP连接类中
std::atomic<bool> g_running = true;
SOCKET sock;

void SendRecive(SOCKET *isock) {
    char buf[4096];
    while (g_running) {
        ZeroMemory(buf, 4096);
        auto byteRecived = recv(*isock, buf, 4096, 0);
        if (byteRecived <= 0) {
            // 服务端断开或读取错误时退出循环
            if (byteRecived == 0) {
                std::cout << "服务端已断开连接" << std::endl;
            }
            break;
        }
        std::cout << "SERVER> " << std::string(buf, 0, byteRecived) << std::endl;
    }
    g_running = false;
}

// 单独的发送线程逻辑示例
void SendLogic(SOCKET *isock) {
    while (g_running) {
        std::string input;
        std::getline(std::cin, input);
        if (input == "quit") {
            g_running = false;
            break;
        }
        send(*isock, input.c_str(), input.size(), 0);
    }
}

int main() {
    TCPConnection tcpconn("192.168.1.4", 7705, &sock);    
    std::thread recvThread(SendRecive, &sock);
    std::thread sendThread(SendLogic, &sock);

    // 解绑线程,不阻塞主逻辑
    recvThread.detach();
    sendThread.detach();

    // 这里可以执行其他主逻辑
    while (g_running) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    // 等待线程退出后再销毁连接资源
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    return 0;
}

注意事项

  • 多线程同时操作std::cout输出时需要加锁,避免输出内容乱序。
  • 退出标记必须使用std::atomic类型保证线程可见性,禁止使用普通bool变量。
  • 进阶实现可以将收发线程封装到TCPConnection类内部,在析构函数中等待线程退出后再清理socket资源,生命周期管理更安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:57:03