在LINUX系统中,系统默认TCP建立连接超时时间为127秒。但是对于应用程序来说,这个超时时间太长了,不利于一些业务的处理。比如说我的应用想通过建立TCP连接来判断服务端程序是否在运行,或者网络是否通达,这时我不可能等127秒。那么应用程序如何实现TCP连接超时呢?
首先我们来看connect函数的帮助说明:
man connect
EINPROGRESS
The socket is non-blocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates
writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual
error codes listed here, explaining the reason for the failure).
解释如下:
首先设置socket描述符为非阻塞模式,然后调用connect建立连接,此时连接操作不会立即完成,会返回错误码EINPROGRESS。然后使用select或者epoll来监测socket的写事件,如果超时时间内没有写事件到达,说明连接超时。如果有写事件时,需要获取socket错误码,错误为0时表示连接成功,错误码不为0时表示连接失败。文章来源:https://www.toymoban.com/news/detail-536022.html
下面我们按照帮助说明编写一个简单的客户端demo程序来实现连接超时,供大家参考:文章来源地址https://www.toymoban.com/news/detail-536022.html
#include<sys/socket.h>
#include<sys/select.h>
#include<string.h>
#include<stdio.h>
#include<arpa/inet.h>
#include<errno.h>
int main(int argc,char *argv[])
{
//设为非阻塞
int sockfd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, 0);
printf("sockfd: %d\n", sockfd);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = inet_addr("192.168.1.2");
socklen_t socklen = sizeof(struct sockaddr);
int ret = connect(sockfd, (struct sockaddr*)&sin, socklen);
printf("connect ret: %d\n", ret);
if(ret != 0)
{
if(errno == EINPROGRESS)
{
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(sockfd, &writefds);
struct timeval stm;
stm.tv_sec = 3;
stm.tv_usec = 0;
ret = select(sockfd+1, NULL, &writefds, NULL, &stm);
printf("select ret: %d\n", ret);
//没有写事件,表示连接超时
//比如,对端不可达
if(0 == ret)
{
printf("connect time out\n");
}
//有一个写事件
else if (1 == ret)
{
if(FD_ISSET(sockfd, &writefds))
{
printf("fd is set\n");
//连接成功时val为0
//连接失败时val非0,比如对端没有绑定该端口,val返回111,连接拒绝
int val;
ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &val, &socklen);
printf("getsockopt ret: %d\n", ret);
printf("err code: %d, [%s]\n", val, strerror(val));
}
}
}
else
{
printf("%s\n", strerror(errno));
}
}
close(sockfd);
return 0;
}
到了这里,关于TCP连接超时处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!