`
阅读更多
关于非阻塞式socket的connect
 
 

    在网络编程中经常要用到非阻塞式的socket,尤其在一些嵌入式场合。翻看了一下linux的man[man connect],有这么一段话:

EINPROGRESS
     The  socket is non-blocking and the connection cannot be completed immediately.  It is possible to select(2) or poll(2) for completion by selecting the socket for  writing.   After  select(2) indicates  writability,  use  getsockopt(2)  to read the SO_ERROR option at level SOL_SOCKET to determine whether  connect()  completed  successfully  (SO_ERROR  is  zero)  or  unsuccessfully (SO_ERROR  is one of the usual error codes listed here, explaining the reason for the failure).

    大致意思就是说对于非阻塞式的socket,由于不能立即完成connect操作(比如TCP的三次握手),会返回EINPROGRESS这个errno,我们应该认为这是正常的,然后用select或poll调用来确定是否可写(这里就可以设置多长时间之内可写来达到不会等待很久,如果不是非阻塞式的socket,系统回尝试很多次之后才返回失败,具体多长时间跟OS有关),也就是说,不管成功还是失败,都会可写,那怎么区分呢?用getsockopt()调用来确认errno,如果errno不为0(success),就可以判断为失败。

   以下是一个模板:

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
    {
        fprintf(stderr, "socket() failed: %s\n", strerror(errno));
        goto error_quit;
    }

    if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK) < 0)   //非阻塞
    {
        fprintf(stderr, "fcntl() failed: %s\n", strerror(errno));
        goto error_quit;
    }

    .......bind()之类的操作



    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(server_ip);    //转换为网络字节序
    server_addr.sin_port = htons(server_port);
    retval = connect(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (retval < 0)
    {
        struct timeval = {1, 5000};    //在1.005s内还没有返回则认为失败
        fd_set writeable;

        //返回EINPROGRESS是正常的,因为3次TCP握手还在进行中
        if (errno != EINPROGRESS)
        {
            fprintf(stderr, "connect() failed: %s\n", strerror(errno));
            goto error_quit;
        }

        FD_ZERO(&writeable);
        FD_SET(fd, &writeable);
        //连接成功或者失败都会writeable
        retval = select(fd+1, NULL, &writeable, NULL, &tv);
        FD_CLR(fd, &writeable);
       
        if (retval < 0)
        {
            //调用失败
            fprintf(stderr, "select() failed: %s\n", strerror(errno));
            goto error_quit;
        }
        else if (retval == 0)
        {
            //超时,在规定时间内还不能可写
            goto error_quit;
        }
        else
        {
            int error = 0;
            socklen_t len = sizeof(int);

            //成功的话error应该为0
            if ((getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) || (0 != error))
            {
                fprintf(stderr, "connect failed: %s\n", strerror(error));
                goto error_quit;
            }
        }//select
分享到:
评论

相关推荐

    MySQLERROR:1005Canx27tcreatetable(erron:150)解决办法.pdf

    erron:150相关介绍 当你试图在mysql中创建一个外键的时候,这个出错会经常发生,这是非常令人沮丧的。像这种不能创建一个.frm 文件的报错好像暗示着操作系统的文件的权限错误或者其它原因,但实际上,这些都不是的

    AT指令资料

    - **回应码**:`OK:n=0,1,2,3` 和 `ERRON:n设为其他值`,其中n=0表示关闭喇叭,n=1表示在检测到载波后关闭喇叭,n=2表示在摘机状态下始终打开喇叭,n=3表示除拨号期间外,在检测到载波后关闭喇叭。 ##### Nn - 调制...

    轻松OBS录屏黑屏解决办法(原创文章请勿转载)NVENC Error:init_encoder:报错信息

    标题中的“轻松OBS录屏黑屏解决办法”是指针对OBS Studio软件在录屏时出现黑屏问题的一种解决方案。OBS Studio是一款免费且开源的屏幕录制与直播软件,广泛应用于游戏直播、教学视频制作等领域。...

    C语言之2048小游戏理解分析

    `get_errorInfo`函数接收一个枚举类型的参数`mc_erron`,表示错误类型,并输出预定义的错误信息。这个函数通常用于在程序中出现错误时提供有用的反馈。 2. **方向选择信息处理**: ```c int get_chooseInfo(enum...

    Geoda学习全套资料,均为自己学习整理,基本涵盖论文所需全部操作,包括LISA集聚图、莫兰散点图、自然断点图、四分位数图

    •GM/GMM spatial lag GM/GMM spatial lag and erron with options for: .spatial and non-spatial diagnostics •non-spatial endogenous variables heteroskedasticity/HAC and these spatial weights: •...

    进程同步.docx

    发生中断系统调用时,被中断的系统调用返回错误值,而 erron 被设置为 EINTR。 慢系统调用的如下: * 终端设备、管道和网络设备上的文件读取/写入。 * 某些设备上的文件打开 * pause()和 wait()系统调用 * ...

    C语言文件简绍

    以上只是部分C语言头文件的介绍,实际上,C语言头文件还包括更多内容,如错误处理(ERRON.H)、浮点运算(FLOAT.H)、图形操作(GRAPHICS.H)、进程管理(PROCESS.H)、异常处理(SIGNAL.H)、标准I/O(STDIO.H)等...

    基于亚博K210的人脸识别项目python源码.zip

    基于亚博K210的人脸识别项目python源码.zip基于亚博K210的人脸识别项目python源码.zip基于亚博K210的人脸识别项目python源码.zip基于亚博K210的人脸识别项目python源码.zip基于亚博K210的人脸识别项目python源码.zip...

    nodejs-file-downloader

    nodejs-file-downloader 是一个用于下载文件的简单实用程序。 它隐藏了处理流、重定向、路径和重复文件名的复杂性。 可以自动重复失败的下载。 如果您遇到任何错误或有疑问,请不要犹豫,打开一个问题。...

    Unc0ver越狱工具V1-2版

    EL相对稳定版本,自签名无MP。EL一般5次只能能成功,临时应付1.1.4版本MP的erron:60错误

    AwesomeGymAPI:Bootcamp ASP .NET Core-学术界的建筑学API

    很棒的健身房API Bootcamp ASP.NET Core-学术界的建筑学API :wrench: 递归 实体框架 昂首阔步 ... 因此,请执行Clean Solution e re compile或erronãoserámais reproduzido。 4-通过永久性移民/移民

Global site tag (gtag.js) - Google Analytics