zoukankan      html  css  js  c++  java
  • 关于socket的connect超时的问题

    	timeval tm;
    	fd_set set;
    	unsigned long ul = 1;
    	ioctlsocket(sock, FIONBIO, &ul); //设置为非阻塞模式
    	bool ret = false;
    	if (connect(...) == -1)
    	{
    		tm.tv_set  = TIME_OUT_TIME;
    		tm.tv_uset = 0;
    		FD_ZERO(&set);
    		FD_SET(sock, &set);
    
    		if (select(sock, NULL, &set, NULL, &tm) > 0)
    		{
    			getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
    			if (error == 0)
    			{
    				ret = true;
    			}
    			else
    			{
    				ret = false;
    			}
    		}
    		else
    		{
    			ret = false;
    		}
    	}
    	else
    	{
    		ret = true;
    	}
    	ul = 0;
    	ioctlsocket(sock, FIONBIO, &ul); //设置为阻塞模式
    	if(!ret) 
    	{
    		close( sockfd );
    		printf(stderr , "Cannot Connect the server!/n");
    		return;
    	}
    	printf( stderr , "Connected!/n");

    代码思路: 

    1.建立socket
     2
    .将该socket设置为非阻塞模式
     3
    .调用connect()
     4
    .使用select()检查该socket描述符是否可写

     5.根据select()返回的结果判断connect()结果
     6
    .将socket重设置为阻塞模式

    所谓阻塞函数,是指其完成指定的任务之前不允许程序调用另一个函数,在Windows下还会阻塞本线程消息的发送。

    所谓非阻塞函数,是指操作启动之后,如果可以立即得到结果就返回结果,否则返回表示结果需要等待的错误信息,不等待任务完成函数就返回。

    首先,异步函数是非阻塞函数;

    其次,获取远地信息的数据库函数是阻塞函数(因此,WinSock提供了其异步版本);

    下面对具体函数做解释:

    int select(
      __in          int nfds,//本参数忽略,仅起到兼容作用
      __in_out      fd_set* readfds,//指向一组等待可读性检查的套接口,可为NULL
      __in_out      fd_set* writefds,//指向一组等待可写性检查的套接口,可为NULL
      __in_out      fd_set* exceptfds,//指向一组等待错误检查的套接口,可为NULL
      __in          const struct timeval* timeout//select()最多等待时间,对阻塞操作则为NULL
    );
    
    
     

     本函数用于确定一个或多个套接口的状态。对每一个套接口,调用者可查询它的可读性、可写性及错误状态信息。用fd_set结构来表示一组等待检查的套接口

     readfds参数标识等待可读性检查的套接口。如果该套接口正处于监听listen()状态,则若有连接请求到达,该套接口便被标识为可读,这样一个accept()调用保证可以无阻塞完成。对其他套接口而言,可读性意味着有排队数据供读取。或者对于SOCK_STREAM类型套接口来说,相对于该套接口的虚套接口已关闭,于是recv()或recvfrom()操作均能无阻塞完成

    writefds参数标识等待可写性检查的套接口。如果一个套接口正在connect()连接(非阻塞),可写性意味着连接顺利建立。如果套接口并未处于connect()调用中,可写性意味着send()和sendto()调用将无阻塞完成。〔但并未指出这个保证在多长时间内有效,特别是在多线程环境中〕。

    exceptfds参数标识等待带外数据存在性或意味错误条件检查的套接口。请注意如果设置了SO_OOBINLINE选项为假FALSE,则只能用这种方法来检查带外数据的存在与否。对于SO_STREAM类型套接口,远端造成的连接中止和KEEPALIVE错误都将被作为意味出错。如果套接口正在进行连接connect()(非阻塞方式),则连接试图的失败将会表现在exceptfds参数中。

    返回值:
       select()调用返回处于就绪状态并且已经包含在fd_set结构中的描述字总数;如果超时则返回0;否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。


     

  • 相关阅读:
    mybatis
    BeanUtil拷贝
    lombok(@Getter&@Setter)
    fly插件飞向购物车
    原生JavaScript判断是否为邮箱、危险字符、验证长度、验证网址、验证小数、整数、浮点数等常用的 js 验证
    原生JavaScript获取复选框的值
    原生JavaScript获取单选按钮的值
    原生JavaScript实现返回顶部的通用方法
    原生JavaScript获得URL中GET参数值
    原生JavaScript常用的正则表达式
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693661.html
Copyright © 2011-2022 走看看