专栏首页上善若水L011Linux和androidNDK之socket出错情况的处理:Interrupted system call,Try again

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

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,可以改成如下形式:

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

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网络通讯超时时间设置

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 047android初级篇NDK原生程序执行报错

    上善若水.夏
  • L012Linux和androidNDK之执行报错CANNOT LINK EXECUTABLE: cannot locate symbol "signal" referenced by

    上善若水.夏
  • 005互联网网络技术之国内外DNS服务器地址列表

    DNS(Domain Name System)是域名解析服务器的意思,它在互联网的作用是把域名转换成为网络可以识别的IP地址。   通常来说,香港、韩国、日本...

    上善若水.夏
  • Using sparsity to regularize models使用稀疏性来正则化模型

    The least absolute shrinkage and selection operator (LASSO) method is very simil...

    到不了的都叫做远方
  • 《Kotlin Contract 契约》极简教程

    我们都知道Kotlin中有个非常nice的功能就是类型智能推导(官方称为smart cast), 不知道小伙伴们在使用Kotlin开发的过程中有没有遇到过这样的...

    一个会写诗的程序员
  • 数据过于完美就是造假?too sample,GDP数据更加完美!

    这两天,天猫双十一交易额造假的事情持续发酵,因为曲线过于完美,所以受到了很多人的质疑。甚至有些人还用 Python 进行了拟合运算,最终的拟合结果和天猫发布的数...

    周萝卜
  • 【PAT甲级】Maximum Subsequence Sum

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    喜欢ctrl的cxk
  • _CrtSetDbgFlag

    _CrtSetDbgFlag 若要了解有关 Visual Studio 2017 RC 的最新文档,请参阅 Visual Studio 2017 RC 文档。...

    _gongluck
  • Ubuntu 16.04, Python 2.7 安装 TensorFlow CPUUbuntu 16.04, Python 2.7 安装 TensorFlow CPUInstalling Tenso

    iOSDevLog
  • 删除重复字符

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    喜欢ctrl的cxk

扫码关注云+社区

领取腾讯云代金券