connect socket的超时设置

最近项目中,有个需求是检测某ip地址是否是通的,使用了socket的connect函数。但是,当ip地址写错的话,connect就会一直阻塞在那里,大概2、3分钟才能返回连接失败。这对于用户来说是不可接受的。下面的文章介绍了两种方法实现这种超时设置:

转自http://blog.csdn.net/ast_224/article/details/2957294

 connect超时:

目前各平台通用的设置socket connect超时的办法是通过select(),具体方法如下:

1.建立socket;
2.将该socket设置为非阻塞模式;
3.调用connect();
4.使用select()检查该socket描述符是否可写;
5.根据select()返回的结果判断connect()结果;
6.将socket设回阻塞模式。
    //设socket为非阻塞
    unsigned long ul=1;
    int rm=ioctl(sockfd,FIONBIO,&ul);
    if(rm==-1)
    {
      close(sockfd);
      return 0;
    }

    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == 0)
    {
     printf("connected/n");//正常连接(小小:使用gdb调试时,从来走不到这一步"设置为非阻塞,connect调用后,无论连接是否建立立即返回-1")
    }
    if(errno!=EINPROGRESS)//若errno不是EINPROGRESS,则出错(EINPROGRESS:以非阻塞的方式来进行连接的时候,返回的结果如果是 -1,这并不代表这次连接发生了错误,如果它的返回结果是 EINPROGRESS,那么就代表连接还在进行中)
    {
     perror("connect");
     printf("cannot connect:%s/n",server);
     return 0;
    }
    //使用select设置超时
    struct timeval timeout;
    fd_set r;
    FD_ZERO(&r);
    FD_SET(sockfd,&r);
    timeout.tv_sec=0;
    timeout.tv_usec=100;
    int retval = select(sockfd+1,NULL,&r,NULL,&timeout);
    if(retval==-1)
    {
      perror("select");
      return 0;
    }
    else if(retval == 0)
    {
      fprintf(stderr,"Timeout/n");
      return 0;
    }
    printf("%sconnected/n",server);
    //将socket设置回正常的阻塞模式
    ul1=0;
    rm=ioctl(sockfd,FIONBIO,(unsigned long*)&ul1);
    if(rm==-1)
    {
      close(sockfd);
      return 0;
    }

以上代码工作的很好,并且也可以通过getsockopt()获得连接发生错误的确切信息,但这总方法难免觉得有些复杂,因为要涉及到阻塞状态的解除和回置。

这里有个简单的操作方法,同样可以设置连接超时:即通过SO_SNDTIMO套节字参数。

原因是:Linux内核源码中connect的超时参数和SO_SNDTIMO操作的参数一致。

因此,在linux平台下,可以通过connect之前设置SO_SNDTIMO来达到控制连接超时的目的。

    struct timeval timeo;
    socklen_t len = sizeof(timeo);
    timeo.tv_sec = overtime;

    if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1)
    {
        strcpy(reason,strerror(errno));
        perror("setsockopt");
       return 0;
    }

    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(serverStruct->port);
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    bzero(&(their_addr.sin_zero), 8);

    if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
    {
      if (errno == EINPROGRESS)
       {
          strcpy(reason,"timeout");
          return 0;
        }
       strcpy(reason,strerror(errno));
       perror("connect");
       return 0;
    }  

小小:上述两种实现方式都可以达到目的。第二种比较简单,利用直接修改connect内部实现用到的参数。但是这种方式可能会产生其他问题吧?(我不确定),可能会影响到其他socket编程接口的超时设定。根据SO_SNDTIMO字面意思来看,是send time out的意思,感觉可能会影响某些发送数据的函数,比如send

时间: 2024-10-20 14:21:07

connect socket的超时设置的相关文章

perl Socket接收超时设置

一般来说, IO::Socket::INET里的Timeout设置是对于conncet的 如果你想设置recv接收超时, 可以这样设置: 1 usr Socket: 2 ...... 3 setsockopt($socket, SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 1, 0)); 4 #注意这里pack有三个参数, 后面的1表示超时1秒, 最后的0你可以默认 5 #而前面的'l!l!', !表示64位平台 6 #如果你是用IO::Socket::INET他的

C++ Socket超时设置

用winsocket时,send(),recv()过程中有时由于网络状况等原因,收发不能预期进行,可以设置收发时限:int nNetTimeout = 1000; //1秒//发送时限setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof( int ) );//接收时限setsockopt( socket, SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTime

Socket编程实践(9) --套接字IO超时设置方法

引:超时设置3种方案 1. alarm超时设置方法 //代码实现: 这种方式较少用 void sigHandlerForSigAlrm(int signo) { return ; } signal(SIGALRM, sigHandlerForSigAlrm); alarm(5); int ret = read(sockfd, buf, sizeof(buf)); if (ret == -1 && errno == EINTR) { // 超时被时钟打断 errno = ETIMEDOUT;

你应该知道的那些超时设置或默认参数 good

defaultStatementTimeout Sets the number of seconds the driver will wait for a response from the database. Any positive integer Not Set (null) http://www.mybatis.org/mybatis-3/configuration.html 存储介质 Redis Java-Driver Jedis 连接池:Jedis的连接池设计基于 Apache Co

http超时设置

http协议中可以设置超时(连接超时.响应超时),具体设置情景如下: 1.java api的方式: JDK 1.5以前的版本,只能通过设置两个系统属性来控制网络超时: String szUrl = "http://www.ee2ee.com/"; URL url = new URL(szUrl); HttpURLConnection urlCon = (HttpURLConnection)url.openConnection(); //HttpURLConnection是基于HTTP协

JDBC超时设置【转】

恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四层交换机不堪重负,网络变得无法连接,从而导致业务系统也无法正常运转.安全组很快屏蔽了所有的DDos攻击,并恢复了网络,但业务系统却还是无法工作. 通过分析系统的thread dump发现,业务系统停在了JDBC API的调用上.20分钟后,系统仍处于WAITING状态,无法响应.30分钟后,系统抛出

深入理解JDBC的超时设置

恰当的JDBC超时设置能够有效地减少服务失效的时间.本文将对数据库的各种超时设置及其设置方法做介绍. 真实案例:应用服务器在遭到DDos攻击后无法响应 在遭到DDos攻击后,整个服务都垮掉了.由于第四层交换机不堪重负,网络变得无法连接,从而导致业务系统也无法正常运转.安全组很快屏蔽了所有的DDos攻击,并恢复了网络,但业务系统却还是无法工作. 通过分析系统的thread dump发现,业务系统停在了JDBC API的调用上.20分钟后,系统仍处于WAITING状态,无法响应.30分钟后,系统抛出

使用Jsoup获取网页内容超时设置

使用Jsoup获取网页内容超时设置 最近使用Jsoup来抓取网页,并对网页进行解析,发现很好用.在抓取过程中遇到一个问题,有些页面总是报Timeout异常,开始想是不是被抓取网站对IP进行了限制,后来发现用HttpClient可以获取到内容. 原来我最开始使用Jsoup.connect(url).get();方法获取网页内容,这种方式使用的是默认超时时间3秒. 原来Jsoup是可以设置超时的,修改成如下就可以了: Jsoup.connect(url).timeout(30000).get();

基础入门_Python-模块和包.Gevent异步/状态获取/超时设置/猴子补丁?

简单介绍: 说明: Gevent是一个基于libev的并发库,为各种并发和网络相关的任务提供了整洁的API 快速安装: pip install --upgrade gevent 主要模式: 说明: Greenlet以C扩展模块形式接入PY轻量级协程,它们运行于主进程内部,被协作式的调度,且不同于multiprocessing和threading等真正的并行执行,它在同一时刻只能有一个协程在运行 公有方法 gevent.spawn(cls, *args, **kwargs) 创建一个Greenle