zoukankan      html  css  js  c++  java
  • connect设置超时的方法

     在使用TCP的connect连接服务器时,在默认情况下系统使用的是阻塞式socket,如果服务器当前不可用,则connect会等待知道超时时间到达,而这个超时时间是系统内核规定的,并不能使用setSocketOpt来设置,这个函数只能设置send和recv的超时,为了能够随意控制connect的超时时间,可以使用select。大致的过程就是先将socket设置成非阻塞,使用select去轮询套接口,再根据套接口去判断连接状态。

    int connectServer(int sock_fd,unsigned int port,char* ip)
    {
        struct sockaddr_in servaddr;
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(port);
        inet_aton(ip, &servaddr.sin_addr );
    
        fcntl(sock_fd,F_SETFL,fcntl(sock_fd,F_GETFL,0)|O_NONBLOCK);
        int connected = connect(sock_fd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in));
        int ret = -1;
        if (connected != 0 )
    	{
    		if(errno != EINPROGRESS)
    			printf("connect error :%s
    ",strerror(errno));
    		else
    		{
    			struct timeval tm = {2, 0};
    			fd_set wset,rset;
    			FD_ZERO(&wset);
    			FD_ZERO(&rset);
    			FD_SET(sock_fd,&wset);
    			FD_SET(sock_fd,&rset);
    			long t1 = time(NULL);
    			int res = select(sock_fd+1,&rset,&wset,NULL,&tm);
    			long t2 = time(NULL);
    			printf("interval time: %ld
    ", t2 - t1);
    			if(res < 0)
    			{
    				printf("network error in connect
    ");
    			}
    			else if(res == 0)
    			{
    				printf("connect time out
    ");
    			}
    			else if (1 == res)
    			{
    				if(FD_ISSET(sock_fd,&wset))
    				{
    					printf("connect succeed.
    ");
    					fcntl(sock_fd,F_SETFL,fcntl(sock_fd,F_GETFL,0) & ~O_NONBLOCK);
    					ret = 0;
    				}
    				else
    				{
    					printf("other error when select:%s
    ",strerror(errno));
    				}
    			}
    		}
    	}
    
        return ret;
    }
    

     程序先把socket设置成非阻塞,connect在非阻塞模式下会立刻返回,如果没有其他错误,返回值等于0。当connect不能立刻建立连接时,会返回一个EINPROGRESS,表示连接正在建立的过程中,这时我们可以使用select去轮询套接口,而select的轮询超时时间可以根据自己的需要去设置,最主要的是轮询的集合一定要是读和写的集合,即select的第二和第三个参数要赋值,待select返回就可以去判断返回值来确定connect的进程状态了。如果返回值小于0,说明connect的进程出现了错误,如果是等于0则说明connect超时,如果等于1,并且套接口此时的状态是可写,则说明了connect已经成功建立(关于这点大概是因为服务器接收了连接后,不会立刻想socket写数据,这是客户端就只能轮询到可写的socket,我觉得如果服务器接受连接并立刻写数据,在客户端就可能是返回2,这时学要同时判断socket的可读和可写了);其他情况的话就算是其他错误吧,至此,我们只需要设置select的超时值就可以随心所欲地实现自己想要的connect连接超时了。

    最后,别忘了把套接口设置会阻塞状态,毕竟阻塞状态加线程方便控制。

    https://blog.csdn.net/codeheng/article/details/44625495

  • 相关阅读:
    Thinkphp 控制器
    Thinkphp 框架基础
    smarty练习:考试系统
    smarty 自定义函数
    smarty 变量调节器
    python 格式化的三种方法
    python 随机生成汉字
    python中的and和or用法
    pytest 运行用例报错:unknown hook 'pytest_namespace' in plugin <module 'allure.pytest_plugin'
    Jenkins安装插件报错:该Jenkins实例似乎已离线
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/4677644.html
Copyright © 2011-2022 走看看