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

非阻塞accept在连接突发时返回EAGAIN的异常问题咨询

非阻塞accept异常行为:队列多连接仅首次成功,休眠后才可获取后续连接

执行非阻塞accept循环时发现异常行为:当队列中有多个连接请求时,仅首次accept尝试成功,后续所有尝试均返回EAGAIN;但在首次成功accept后休眠一段时间,即可成功获取后续连接。

最小复现示例

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main() {
  // 127.0.0.1:4200
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(4200);
  addr.sin_addr.s_addr = htonl((127 << 24) + 1);

  // create a non blocking socket, listening localhost 4200 port
  int listen_sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
  bind(listen_sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
  listen(listen_sock, 0);

  // make two non-blocking connection request to the above address
  int conn[2];
  for (int i = 0; i < 2; ++i) {
    conn[i] = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
    connect(conn[i], (struct sockaddr*)&addr, sizeof(struct sockaddr_in));
  }

  // after 10 seconds, the two connections above have succeeded
  sleep(10);

  // now perform three `accept` attempt on the listening socket.
  // since there are two connections above,
  // the first two `accept` attempt should succeed,
  // and the third one should return `EAGAIN`
  accept(listen_sock, 0, 0);
  accept(listen_sock, 0, 0);
  accept(listen_sock, 0, 0);

  // but oops, only the first `accept` attempt succeed.
  // the second and third attempt both return `EAGAIN`

  // now sleep for 2 more second and do two more `accept` attempt
  sleep(2);
  accept(listen_sock, 0, 0); // this one succeed
  accept(listen_sock, 0, 0); // this one fail with `EAGAIN` as expected

  close(conn[0]);
  close(conn[1]);
  close(listen_sock);
}

strace运行输出

socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(4200), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
listen(3, 0)                            = 0
socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(4200), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(4200), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=10, tv_nsec=0}, 0x7ffd05a80610) = 0
accept(3, NULL, NULL)                   = 6
accept(3, NULL, NULL)                   = -1 EAGAIN (Resource temporarily unavailable)
accept(3, NULL, NULL)                   = -1 EAGAIN (Resource temporarily unavailable)
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=2, tv_nsec=0}, 0x7ffd05a80610) = 0
accept(3, NULL, NULL)                   = 7
accept(3, NULL, NULL)                   = -1 EAGAIN (Resource temporarily unavailable)
close(4)                                = 0
close(5)                                = 0
close(3)                                = 0

补充实验

  • 若建立三个连接,分三轮调用accept且中间休眠,前两轮accept均仅能接受一个连接,之后返回EAGAIN;但第三轮无论休眠多久,accept始终返回EAGAIN
  • 对三个连接套接字调用getsockopt,未发现错误
  • 通过向连接写入数据验证连接是否成功建立:
    • 在首次accept调用前,第一个连接可写入,写入第二个和第三个连接返回EAGAIN
    • 首次accept调用后立即检查,三个连接均可写入
    • 后续保持可写入状态

现咨询该异常现象的原因及解决办法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 17:28:26