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

非阻塞网络套接字文件描述符何时不可写并触发EAGAIN?

非阻塞网络套接字write()返回EAGAIN的常见场景

当非阻塞网络套接字调用write(fd, buff, len)返回-1且errno设为EAGAIN(或EWOULDBLOCK,两者等价),核心原因是当前无法将数据写入套接字的发送缓冲区,常见场景如下:

  • 发送缓冲区已满
    这是最普遍的情况。TCP套接字的内核发送缓冲区有固定大小(可通过SO_SNDBUF调整),当以下情况发生时,缓冲区会被占满:

    • 对端的TCP接收窗口过小(或为0,即"零窗口"),导致本地发送的数据无法被对端ACK,内核无法释放发送缓冲区空间;
    • 短时间内向套接字写入了大量数据,超过了缓冲区剩余可用空间;
    • 网络拥塞导致数据在链路中堆积,内核无法及时将缓冲区数据发送出去。
  • TCP连接处于未完全建立状态
    针对非阻塞TCP套接字:如果调用connect()后,连接还处于SYN_SENT或SYN_RECV阶段(即三次握手未完成),此时调用write()会返回EAGAIN。必须等待连接完全建立(比如通过epoll监听EPOLLOUT事件)后,才能正常写入数据。

  • 未等待可写事件触发就执行写入
    在使用epoll等多路复用工具时,如果没有先监听并等待EPOLLOUT事件触发就直接调用write(),此时若发送缓冲区没有足够空间,就会立即返回EAGAIN。正确的做法是当epoll通知EPOLLOUT时,再执行写入操作。

  • UDP套接字缓冲区耗尽
    虽然UDP无连接,但如果短时间内发送大量UDP数据包,导致内核的UDP发送缓冲区被占满,非阻塞模式下调用write()也会返回EAGAIN。不过这种情况比TCP少见,因为UDP本身不保证交付,内核对UDP缓冲区的限制相对宽松。

需要注意:如果对端关闭了套接字(发送FIN或RST),此时调用write()通常会返回EPIPE(忽略SIGPIPE信号时),而非EAGAIN,这不属于你问的场景。

内容的提问来源于stack exchange,提问作者Aritra Sur Roy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:15:36