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

如何在向非阻塞Socket发送数据时模拟EAGAIN或EWOULDBLOCK错误?

模拟非阻塞Socket send返回EAGAIN并触发EPOLLOUT的测试方法

嗨,这个测试场景我做网络编程的时候也折腾过,分享几个靠谱的模拟方法,帮你把重发代码的测试覆盖到:

方法一:缩小发送缓冲区强制填满

这是最直接的代码层面模拟方式:

  • 在创建非阻塞Socket后,调用setsockopt将发送缓冲区SO_SNDBUF设置为极小值(比如128字节):
    int buf_size = 128;
    setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size));
    
  • 随后尝试发送远大于缓冲区容量的数据(比如一次性发1024字节):第一次send可能会返回部分成功写入的字节数,继续调用send就会触发EAGAIN/EWOULDBLOCK错误。
  • 此时注册epoll_ctl监听该Socket的EPOLLOUT事件,epoll很快就会触发该事件(内核缓冲区的可用空间变化会触发通知),你就能测试重发逻辑了。

方法二:用本地回环Socket配合接收端不读取数据

利用本地socket的特性,人为让发送缓冲区饱和:

  • 创建一对本地Socket(可以用socketpair创建AF_UNIX域的socket对,或者让客户端连接本地的TCP服务器)。
  • 让接收端完全不调用recv读取数据,发送端以非阻塞模式持续发送大体积数据。
  • 当发送端的send返回EAGAIN/EWOULDBLOCK后,向epoll注册EPOLLOUT事件。此时只要让接收端读取少量字节(比如调用一次recv读几个字节),发送端的epoll就会立刻触发EPOLLOUT,触发你的重发流程。

方法三:用流量控制工具模拟(适合更真实的网络场景)

如果想模拟更接近真实网络的阻塞情况,可以用Linux的tc工具限制网卡的发送速率:

  • 比如在本地回环网卡上设置极低的发送带宽:
    tc qdisc add dev lo root tbf rate 1kbit burst 100b latency 70ms
    
  • 此时发送端快速发送大量数据时,内核缓冲区会很快被填满,send就会返回EAGAIN,之后当带宽有空闲时,epoll会触发EPOLLOUT事件。测试完成后记得删除规则:
    tc qdisc del dev lo root
    

测试注意事项

  • 注意区分epoll的边缘触发(EPOLLET)和水平触发模式:如果是边缘触发,要确保在EPOLLOUT事件触发时尽可能发送数据直到再次返回EAGAIN;如果是水平触发,要避免陷入循环发送的忙等状态。
  • 测试完成后记得恢复Socket的缓冲区设置,避免影响其他测试逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:07:47