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\n",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\n", t2 - t1);
			if(res < 0)
			{
				printf("network error in connect\n");
			}
			else if(res == 0)
			{
				printf("connect time out\n");
			}
			else if (1 == res)
			{
				if(FD_ISSET(sock_fd,&wset))
				{
					printf("connect succeed.\n");
					fcntl(sock_fd,F_SETFL,fcntl(sock_fd,F_GETFL,0) & ~O_NONBLOCK);
					ret = 0;
				}
				else
				{
					printf("other error when select:%s\n",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连接超时了。

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


 

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 CSDN 开发的 C 知道 中,您可以使用一些套接字选项来设置 TCP 连接的超时时间。一种常用的方法是使用 `connect()` 函数之前,使用 `setsockopt()` 函数设置 `SO_RCVTIMEO` 或 `SO_SNDTIMEO` 选项。 以下是一个示例代码片段,展示了如何设置连接超时时间为 5 秒: ```c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main() { int sockfd; struct sockaddr_in server_addr; int connect_timeout = 5; // 超时时间为 5 秒 // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(1); } // 设置连接超时选项 struct timeval timeout; timeout.tv_sec = connect_timeout; timeout.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { perror("setsockopt"); exit(1); } if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) == -1) { perror("setsockopt"); exit(1); } // 设置服务器地址 server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8080); // 设置服务器端口号 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 设置服务器 IP 地址 // 连接服务器 if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { perror("connect"); exit(1); } // 连接成功,进行后续操作 // 关闭套接字 close(sockfd); return 0; } ``` 在上述示例中,我们使用了 `setsockopt()` 函数来设置 `SO_RCVTIMEO` 和 `SO_SNDTIMEO` 选项,将超时时间设置为 5 秒。这样,在调用 `connect()` 函数时,如果连接超时或者连接过程中发生错误,会返回相应的错误码。 请注意,以上代码仅用于演示如何设置连接超时时间,实际应用中可能需要根据具体情况进行适当修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值