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

为何Socket的recv()函数未进入带超时的阻塞模式

解决TCP服务器recv()带超时阻塞失效的问题

我之前遇到过一模一样的坑!大概率是你的监听socket(_serverSocket)带了非阻塞属性,导致accept()返回的客户端socket自动继承了这个特性——这时候哪怕你设置了SO_RCVTIMEO,recv()也会直接进入非阻塞模式,根本不会等待超时。

先给你拆解问题核心:

  • 如果监听socket之前被设置为非阻塞(比如用fcntl加了O_NONBLOCK),客户端socket会继承这个属性,此时SO_RCVTIMEO完全不起作用。
  • 你设置的SO_LINGER和recv()的阻塞行为无关,这个选项是控制socket关闭时的 linger 逻辑,可以暂时保留或删掉,不是问题根源。
  • 之前尝试的MSG_WAITALL,只有在socket处于阻塞模式且超时设置生效的前提下才会起作用,非阻塞状态下它也无能为力。

下面是修复后的代码,我加上了关键的处理步骤:

int clientSocket = accept(_serverSocket, (struct sockaddr *)NULL, NULL); 
if (clientSocket < 0) {
    perror("accept failed");
    return -1;
}

// 第一步:将客户端socket从非阻塞改回阻塞模式(如果监听socket是非阻塞的)
int flags = fcntl(clientSocket, F_GETFL, 0);
if (flags != -1) {
    // 清除O_NONBLOCK标志,恢复阻塞模式
    if (fcntl(clientSocket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
        perror("fcntl set block failed");
        close(clientSocket);
        return -1;
    }
}

// 第二步:设置接收超时,务必检查setsockopt是否成功
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500 * 1000; // 500ms超时
int sockOptRet = setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
if (sockOptRet == -1) {
    perror("setsockopt SO_RCVTIMEO failed");
    close(clientSocket);
    return -1;
}

// 可选:SO_LINGER不影响recv阻塞,不需要可以删除
// struct linger sl;
// sl.l_onoff = 1;
// sl.l_linger = 0;
// setsockopt(clientSocket, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl));

char _rcvBuffer[sizeof(can_frame)];
int numBytesRcv = recv(clientSocket, _rcvBuffer, sizeof(can_frame), 0);

// 处理recv返回值:超时会返回-1,对应errno为EAGAIN/EWOULDBLOCK
if (numBytesRcv == -1) {
    if (errno == EAGAIN || errno == EWOULDBLOCK) {
        printf("recv timed out\n");
    } else {
        perror("recv failed");
    }
} else if (numBytesRcv == 0) {
    printf("client disconnected\n");
} else {
    printf("received %d bytes\n", numBytesRcv);
}

现在再测试的话,recv()应该会以带500ms超时的阻塞模式运行了——如果到时间没收到数据,就会返回-1并触发EAGAIN/EWOULDBLOCK错误,你可以根据这个逻辑处理超时场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:06:37