转载请注明来源:https://www.cnblogs.com/hookjc/



将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,即:
设置成非阻塞模式:

先用fcntl的F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK;        

即:

 

      flags = fcntl(sockfd, F_GETFL, 0);                        //获取文件的flags值。

      fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);   //设置成非阻塞模式;

同时在接收和发送数据时,需要使用MSG_DONTWAIT标志

即:

      在recv,recvfrom和send,sendto数据时,将flag设置为MSG_DONTWAIT。

设置成阻塞模式:

 

先用fcntl的F_GETFL获取flags,用F_SETFL设置flags&~O_NONBLOCK;      

即:

     flags  = fcntl(sockfd,F_GETFL,0);                          //获取文件的flags值。

     fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK);    //设置成阻塞模式;            

同时在接收和发送数据时,需要使用阻塞标志

即:

        在recv,recvfrom和send,sendto数据时,将flag设置为0,默认是阻塞。       

 

在将socket设置成非阻塞模式后,每次的对于sockfd 的操作都是非阻塞的;

非阻塞模式下:

connect   

       =0   当返回0时,表示立即创建了socket链接,

       <0   当返回-1时,需要判断errno是否是EINPROGRESS(表示当前进程正在处理),否则失败。

       例如:下面会有select或epoll监听fd是否建立链接,

        select监听connect是否成功的例子,注意getsockopt验证,因为三次握手的第三个ACK有可能会丢失,但是客户端认为链接已经建立:

int ret = ::connect(_socket_fd, add.addr(), add.length());
if(ret == 0)
{
            //建立链接成功
}
else if(ret < 0 && errno == EINPROGRESS)          //errno == EINPROGRESS表示正在建立链接
{
     // 等待连接完成,errno == EINPROGRESS表示正在建立链接
     fd_set set;
     FD_ZERO(&set);
     FD_SET(_socket_fd,&set);  //相反的是FD_CLR(_sock_fd,&set)


     time_t = 10;          //(超时时间设置为10毫秒)
     struct timeval timeo;
     timeo.tv_sec = timeout / 1000; 
     timeo.tv_usec = (timeout % 1000) * 1000;

 

     int retval = select(_socket_fd + 1, NULL, &set, NULL, &timeo);           //事件监听
     if(retval < 0)   
     {
            //建立链接错误close(_socket_fd)
     }
     else if(retval == 0) // 超时
     {
            //超时链接没有建立close(_socket_fd)
     }

     //将检测到_socket_fd读事件或写时间,并不能说明connect成功
     if(FD_ISSET(_socket_fd,&set))
     {
           int error = 0;
           socklen_t len = sizeof(error);
           if(getsockopt(_socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
           {
                  //建立简介失败close(_socket_fd)
           }
           if(error != 0) // 失败
           {
                  //建立链接失败close(_socket_fd)
           }
           else
            {
                  //建立链接成功
            }
     }
}
else
{
      //出现错误 close(_sock_fd)
}

注意:这里主要是想强调当epoll或select监听到sockfd上有EPOLL_IN或EPOLL_OUT时,即读写事件时,并不能说明链接已经建立,如上面的代码。

/*

int error = 0;
socklen_t ilen = sizeof(error);
ret = getsockopt(fd,SOL_SOCKET,SO_ERROR,&error,&ilen);
if(ret < 0)
{
      //说明链接建立失败,close(fd);
}
else if(error != 0 )
{

     //说明链接建立失败,close(fd);
}

else

{

       //说明链接建立成功。即可以向fd上写数据。

}

 */                      

 recv 和 recvfrom

       =0  当返回值为0时,表示对端已经关闭了这个链接,我们应该自己关闭这个链接,即close(sockfd)。另外因为异步操作会用select或epoll做事件触发,所以:

       1、如果使用select,应该使用FD_CLR(sockfd,fd_set)将sockfd清除掉,不再监听。

       2、如果使用epoll,系统会自己将sockfd清除掉,不再进行监听。

       >0 当返回值大于0 且 小于sizeof(buffer)时,表示数据肯定读完。(如果等于sizeof(buffer),可能有数据还没读,应该继续读,不可能有大于)

       <0 当返回值小于0,即等于-1时,分情况判断:

        1、如果   errno   为  EAGAIN  或 EWOULDBLOCK                                      

                表示暂时无数据可读,可以继续读,或者等待epoll或select的后续通知。(EAGAIN,EWOULDBLOCK产生的

         原因:可能是多进程读同一个sockfd,可能一个进程读到数据,其他进程就读取不到数据(类似惊群效应),当然

         单个进程也可能出现这种情况。对于这种错误,不需用close(sockfd)。可以等待select或epoll的下一次触发,

         继续读。)

         2、如果   errno   为  EINTR

                表示被中断了,可以继续读,或者等待epoll或select后续的通知。

                否则,真的是读取数据失败。(此时应该close(sockfd))

 

send和sendto      

        返回值是实际发送的字符数,因为我们知道要发送的总长度,所以,如果没有发送完,我们可以继续发送。

          <0 当返回值为 -1   时, 我们需要判断  errno:

                1、如果errno为  EAGAIN   或 EWOULDBLOCK ,表示当前缓冲区写满,可以继续写,

                      或者等待epoll或select的后续通知,一旦有缓冲区,就会触发写操作,这个也是经常利用的一个特性。  

                 2、如果errno为EINTR  ,表示被中断了,可以继续写,或者等待epoll或select的后续通知。

                       否则真的出错了,即errno不为EAGAIN或EWOULDBLOCK或EINTR,此时应该close(sockfd)

          >=0 >=0且不等于要求发送的长度,应该继续send,如果等于要求发送的长度,发送完毕。

来源:python脚本自动迁移

linux 设置connect 超时的更多相关文章

  1. linux 设置connect 超时代码[select/epoll]

    转载请注明来源:https://www.cnblogs.com/hookjc/ linux下socket编程有常见的几个系统调用: 对于服务器来说, 有socket(), bind(),listen( ...

  2. Linux下connect超时处理【总结】

    1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的应用层, ...

  3. Linux下connect超时处理

    1.前言 最近在写一个测试工具,要求快速的高效率的扫描出各个服务器开放了哪些端口.当时想了一下,ping只能检测ip,判断服务器的网络是连通的,而不能判断是否开放了端口.我们知道端口属于网络的传输层, ...

  4. linux下connect超时时间探究

    最近在linux做服务器开发的时候,发现了一个现象:服务器在启动的时候调用了 connect 函数,因为连接了一个不可用的端口,导致connect最后报出了 “Connection timed out ...

  5. iOS 设置connect超时

    NSLock *theLock; [theLock lock]; int fd, error; struct sockaddr_in addr; ))<) { cout<<" ...

  6. VC socket Connect 超时时间设置

    设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...

  7. C Socket编程之Connect超时 (转)

    网络编程中socket的分量我想大家都很清楚了,socket也就是套接口,在套接口编程中,提到超时的概念,我们一下子就能想到3个:发送超时,接收超时,以及select超时(注:select函数并不是只 ...

  8. 设置linux中tcp默认的20秒connect超时时间(转)

    无论你用任何语言或者是网络库,你都可以设置网络操作的超时时间,特别是connect.read.write的超时时间. 你可以在代码中把超时时间设置任意大小值,但是connect方法会有一点特殊. co ...

  9. linux ssh连接超时断连设置

    以下均针对redhat6.5系统进行说明. 一.设置ssh超时断连 使用root用户,编辑/etc/profile文件,在 HOSTNAME='/bin/hostname' HISTIZE=30 后增 ...

随机推荐

  1. 动态规划题 HDU-1024

    http://acm.hdu.edu.cn/showproblem.php?pid=1024 Now I think you have got an AC in Ignatius.L's " ...

  2. Java程序设计基础作业目录(作业笔记)

    持续更新中............. Java程序设计基础笔记 • [目录] 我的大学笔记>>> 第1章 初识Java>>> 1.1.4 学生成绩等级流程图练习 1 ...

  3. 使用 DML语句,对 “锦图网” 数据进行操作,聚合函数练习

    查看本章节 查看作业目录 需求说明: 根据客户 ID 统计订单数.订单总金额.最高订单金额.最低订单金额和每份订单平均金额,并按订单总金额升序显示 根据客户统计订单总订购人次数> 5 的统计信息 ...

  4. GeoWave实践2:使用命令行将本地矢量数据注入hbase并发布至GeoServer

    目录 步骤 补充 步骤 在GeoWave所在的节点打开两个会话窗口. 会话1 //运行GeoServer,默认端口8080 geowave gs run 会话2 //为GeoWave创建数据库Test ...

  5. Go语言系列之函数

    函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数 Go语言中支持函数.匿名函数和闭包,并且函数在Go语言中属于"一等公民". 函数 ...

  6. nuxt中iview按需加载配置

    在plugins/iview.js中修改 初始代码如下 import Vue from 'vue' import iView from 'iview' import locale from 'ivie ...

  7. asp.net core 中优雅的进行响应包装

    目录 摘要 正常响应/模型验证错误包装 实现按需禁用包装 如何让 Swagger 识别正确的响应包装 禁用默认的模型验证错误包装 使用方法以及自定义返回结构体 SourceCode && ...

  8. Keil MDK STM32系列(六) 基于抽象外设库HAL的ADC模数转换

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  9. 【Java】Eclipse常用快捷键

    Eclipse常用快捷键 * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl + / * ...

  10. day 10 删除空白字符

    (1).有以下程序(大写变小写) (2).有以下程序,在[1]填写程序,使得程序正确运行. 分析:(*p)(int,int)是一个函数指针(一个指针[*p]指向的对象是一个函数),函数的形参是(int ...