赞
踩
使用阻塞的socket, 可以设置读写超时,
struct timeval tv_timeout;
tv_timeout.tv_sec = 60;
tv_timeout.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *) &tv_timeout, sizeof(struct timeval)) < 0) {
perror(“setsockopt”);
}
tv_timeout.tv_sec = 60;
tv_timeout.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &tv_timeout, sizeof(struct timeval)) < 0) {
perror(“setsockopt”);
}
但是这个不会影响connect.
如何设置connect超时呢, 通过信号alarm? 感觉不是一个好的办法.比较好的办法是通过select或者poll判断超时.
首先设置socket fd为非阻塞, connect判断返回值, 如果返回0, 说明connect成功, 如果返回值等于-1并且错误的errno为EINPROGRESS时调用select或者poll判断socket fd的可写状态, 通过select或者poll的超时设置来判断是否超时.
man page是这么写的
EINPROGRESS
The socket is non-blocking and the connection cannot be com-
pleted 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() com-
pleted successfully (SO_ERROR is zero) or unsuccessfully
(SO_ERROR is one of the usual error codes listed here, explain-
ing the reason for the failure).
下边是示例代码:
int opt = 1;
//set non-blocking
if (ioctl(sockfd, FIONBIO, &opt) < 0) {
close(sockfd);
perror(“ioctl”);
exit(0);
}
if (connect(sockfd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) == -1) {
if (errno == EINPROGRESS) {
int error;
int len = sizeof(int);
tv_timeout.tv_sec = 60;
tv_timeout.tv_usec = 0;
FD_ZERO(&set);
FD_SET(sockfd, &set);
if(select(sockfd + 1, NULL, &set, NULL, &tv_timeout) > 0) {
getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
if(error != 0) {
close(sockfd);
exit(0);
}
} else { //timeout or select error
close(sockfd);
exit(0);
}
} else {
close(sockfd);
perror(“connect”);
exit(0);
}
}
opt = 0;
//set blocking
if (ioctl(sockfd, FIONBIO, &opt) < 0) {
close(sockfd);
perror(“ioctl”);
exit(0);
}
转载自qianshen88
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。