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

C语言Socket客户端高并发场景下poll调用挂死问题求助

问题代码分析
#define RETRY_TIMEOUT 2

while(1)
{
    read_size = SocketReceive(hSocket, recvBuf, sizeof(recvBuf),
                              rsHndl, RETRY_TIMEOUT);
}

int SocketReceive(int hSocket,uint8_t* Rsp,short RvcSize, EMHANDLE *rsHndl,
                                      unsigned short timeout)
{                                     
    struct pollfd fds[1];
    int rv = -1;

    fds[0].fd = hSocket;
    fds[0].events = POLLIN;

    if ((rv = poll(fds, 1, timeout * 1000) > 0))
    {
        if (fds[0].revents & POLLIN)
        {
            shortRetval = recv(hSocket, Rsp, RvcSize, 0);
        }
    }
}

核心错误点

  1. 运算符优先级错误
    if ((rv = poll(fds, 1, timeout * 1000) > 0)) 代码中>的运算优先级高于赋值运算符=,实际执行逻辑等价于rv = (poll(...) > 0),rv只会被赋值为1或0,完全丢失了poll返回-1的错误场景信息。高并发场景下触发系统调用错误时,代码无法识别异常,也不会做对应处理。
  2. poll返回值处理逻辑缺失
    当前代码仅处理了poll返回>0的情况,完全忽略另外两种合法返回值:
  • 返回0:超时场景,你设置的2秒超时完全没有生效,超时后函数无有效返回,外层死循环会立刻再次调用poll,相当于超时参数失效
  • 返回-1:系统调用错误,没有对应错误处理逻辑,比如EINTR信号中断可重试,文件描述符异常需要直接关闭连接退出
  1. revents异常事件未处理
    仅判断了POLLIN事件,没有处理POLLERR(套接字错误)、POLLHUP(对端挂断)、POLLNVAL(文件描述符非法)这些高并发场景下极易触发的异常事件。这类事件触发时,poll正常返回但不会走POLLIN分支,函数无有效动作,外层死循环不断调用poll,最终表现为挂死。
  2. 基础语法缺陷
  • SocketReceive声明为int返回类型,但代码中没有显式return语句,返回值是未定义的随机值,外层循环的判断逻辑完全失效
  • 代码中用到的shortRetval没有声明定义

修复后参考代码

#define RETRY_TIMEOUT 2

while(1)
{
    read_size = SocketReceive(hSocket, recvBuf, sizeof(recvBuf),
                              rsHndl, RETRY_TIMEOUT);
    // 外层添加返回值判断,异常时退出循环
    if (read_size < 0) {
        close(hSocket);
        break;
    } else if (read_size == 0) {
        // 超时场景按需处理
        continue;
    }
    // 正常处理接收数据
}

int SocketReceive(int hSocket,uint8_t* Rsp,short RvcSize, EMHANDLE *rsHndl,
                                      unsigned short timeout)
{                                     
    struct pollfd fds[1];
    int rv = -1;
    short shortRetval = 0; // 补全变量定义

    fds[0].fd = hSocket;
    fds[0].events = POLLIN;

    rv = poll(fds, 1, timeout * 1000); // 先赋值再判断,修正优先级问题
    if (rv < 0) {
        // 处理poll错误
        if (errno == EINTR) {
            return 0; // 信号中断,可重试
        }
        return -1; // 其他错误返回异常
    } else if (rv == 0) {
        // 超时返回
        return 0;
    }

    // 优先处理异常事件
    if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
        return -1; // 套接字异常返回错误
    }

    if (fds[0].revents & POLLIN) {
        shortRetval = recv(hSocket, Rsp, RvcSize, 0);
        // 补全recv返回值处理
        if (shortRetval <= 0) {
            return -1;
        }
        return shortRetval;
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 11:18:01