blocking socket 读写返回 EAGAIN

18 篇文章 0 订阅

非阻塞的 socket 读写操作返回 EAGAIN,表示当前已经读完内核缓冲区或者写满内核缓冲区,需要等待下一次 select/poll/epoll 事件到来时再操作。

对于阻塞的 socket 读写操作,如果内核缓冲区是空,read 将一直阻塞;如果不能一下全部写入用户态缓冲区的所有数据,write 将阻塞。原以为对于阻塞的 socket,如果设置超时时间,读操作内核缓冲区为空或写操作内核缓冲区已满,返回的是 ETIMEDOUT,原来返回的也是 EAGAIN.

内核缓冲区还有 4 个字节的剩余空间,那么对于阻塞操作,如果需要写入 6 个字节,就会一直阻塞,直到 6 个字节全部写入内核缓冲区;如果设置超时,那么第一次写入会直接返回 4,表示写入了 4 个字节;第二次写入操作才返回 EAGAIN.

那么总结起来,对于 socket 操作,返回 EAGAIN 的有如下 3 钟情况。

  1. explicitly marking the file descriptor as nonblocking with fcntl();
  2. passing the MSG_DONTWAIT flag to send()
  3. setting a send timeout with the SO_SNDTIMEO socket option

 

下边一系列实验都是在当前本端发送缓冲区已满的情形下进行并且在此过程中,对端不进行读取操作。

1、socket 的写入操作会一直阻塞,使用 ctrl + C终止。

2、阻塞套接字设置 MSG_DONTWAIT 标志,表示本次操作非阻塞,立即返回 EAGAIN,在python 里就是抛 BlockingIOError.

3、阻塞套接字设置 SO_SNDTIMEO 发送超时选项,阻塞直到超时后返回,在python 里就是抛 BlockingIOError.

4、在 python 里,单独有个方法可以设置超时:.settimeout(),次方法不是通过设置套接字选项来实现的。下边的代码片段先关闭通过套接字选项设置的超时(通过给选项参数设置为 0),然后通过 .settimeout 方法设置超时,注意超时时,抛出的是 timeout异常,errno 并没有被设置。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值