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

为何C#端关闭socket会导致C++树莓派服务端主线程意外终止?

问题根因

你的C++服务端进程退出是SIGPIPE信号触发的默认终止行为,和主线程、子线程逻辑无关:

  • Linux/Unix系统下,当进程尝试向已经被对端关闭的TCP socket执行send()操作时,内核会向进程发送SIGPIPE信号,该信号的默认处理动作是直接终止整个进程
  • C++的try/catch只能捕获语言层面的异常,无法捕获系统信号,所以你写的异常捕获逻辑完全不会触发,这也对应你给出的日志里没有输出SC error、SC thread exited就直接退出的现象

解决方案

1. 忽略SIGPIPE信号(必改)

在main函数最开头加入忽略SIGPIPE的代码,避免进程被信号直接杀死:

#include <signal.h>

int main()
{
    // 忽略SIGPIPE信号
    signal(SIGPIPE, SIG_IGN);
    
    try
    {
        TestServer::Start();
        // 原有逻辑不变
    }
    // 原有逻辑不变
}

设置后往关闭的socket调用send()不会再触发信号,只会返回-1,同时errno会被设置为EPIPE。

2. 检查send的返回值,处理连接断开场景

你当前的代码完全没有校验send()的执行结果,忽略信号后需要主动判断返回值,连接断开时及时退出循环、关闭socket:

while (true)
{
    int strLen = 9;
    string str = "null:null";

    char b[4] = { (strLen & 0xff), ((strLen >> 8) & 0xff), ((strLen >> 16) & 0xff), ((strLen >> 24) & 0xff) };
    // 检查send返回值
    ssize_t ret = send(new_socket, b, 4, 0);
    if (ret <= 0) break;
    ret = send(new_socket, str.c_str(), strLen, 0);
    if (ret <= 0) break;

    this_thread::sleep_for(chrono::milliseconds(20));
}
// 退出循环后关闭socket
close(new_socket);
close(server_fd);

补充说明

你提到移除LoopOut的循环后问题仍然存在,是因为哪怕只执行一次send(),只要目标socket已经被C#端关闭,就会触发SIGPIPE信号,和是否循环无关。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:36:07