前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >L011Linux和androidNDK之socket出错情况的处理:Interrupted system call,Try again

L011Linux和androidNDK之socket出错情况的处理:Interrupted system call,Try again

作者头像
上善若水.夏
发布2018-09-28 10:55:21
1.1K0
发布2018-09-28 10:55:21
举报
文章被收录于专栏:上善若水

L011Linux和androidNDK之socket出错情况的处理:Interrupted system call,Try again

socket一些出错的情况,并不需要直接结束本次交互,还可以重新启动交互,比如Interrupted system call,Try again。

Timer expired

超时,对于非阻塞的调用,超时系统有一个默认值,不同的系统有不同的设置。(可参看L009Linux和androidNDK之linux网络通讯超时时间设置

如果有设置的话,则使用设置的值。

Interrupted system call

我们用术语慢系统调用(slow system call)描述accept函数,该术语也适用于那些可能永远阻塞的系统调用。永远阻塞的系统调用有可能永远无法返回,多数网络支持函数都属于这一类。举例来说,如果没有客户连接到服务器上,那么服务器的accept调用就没有返回的保证。类似的,如果客户端从未发送过数据,那么read调用将永不返回。其他慢系统调用的例子是对管道和终端设备的读和写。一个值得注意的例外是磁盘IO,它们一般都会返回到调用者(假设没有灾难性的硬件事故)。

适用于慢系统调用的基本规则是:当阻塞于某个慢系统调用的一个进程捕获某个信号且相应处理函数返回时,该系统调用可能返回一个EINTR错误。所以,我们必须对慢系统调用返回的EINTR有所准备。

为了处理被中断的accept,可以改成如下形式:

代码语言:javascript
复制
for (...)
{
    if((connfd=accept(listenfd,NULL, NULL)) < 0)
    {
        if (errno == EINTR)
            continue;
        else
            printf("accept error");
    }
}

这段代码所做的事情就是自己重启被中断的系统调用。对于accept,以及诸如read、write、select和open之类的函数,这是适合的。不过有一个函数我们不能重启:connect。如果该函数返回EINTR,我们就不能再次调用它,否则将立即返回一个错误。当connect被一个捕获信号中断而且不自动重启时,我们必须调用select来等待连接完成。

(出自unix网络编程(第三版)第五章 P115页)

Try again

socket设置SO_RCVTIMEO和SO_SNDTIMEO对read/write的影响?看man怎么说

SO_RCVTIMEO and SO_SNDTIMEO

代码语言:javascript
复制
Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached then -1 is returned witherrno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default) then the operation will never timeout. Timeouts only have effect for system calls that perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for select(2), poll(2), epoll_wait(2), and so on.

即SO_RCVTIMEO和SO_SNDTIMEO会导致read/write函数返回EAGAIN

另外,在确定错误过程中,同事提到O_NODELAY会导致write接口返回EAGAIN,的确,如果设置了O_NODELAY而当前不可写,那么write接口会设置errno为EAGAIN,但是write接口会返回0而不是-1.在本案中,hiredis接口中并没有设置O_NODELAY

参考链接

  1. 阻塞socket上read/write出现errno为EAGAIN的原因解密
  2. Socket编程中Interrupted system call 解释及解决办法
  3. L009Linux和androidNDK之linux网络通讯超时时间设置
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016.08.21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Timer expired
  • Interrupted system call
  • Try again
  • 参考链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档