使用socket选项SO_RCVTIMEO和SO_SNDTIMEO设置超时时间
Posted qq_34132502
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用socket选项SO_RCVTIMEO和SO_SNDTIMEO设置超时时间相关的知识,希望对你有一定的参考价值。
socket
选项SO_RCVTIMEO
和SO_SNDTIMEO
,他们分别 用来设置socket接受 / 发送数据超时时间。
因此,这两个选项仅对数据接收和发送相关的socket专用系统调用有效(send
、sendmsg
、recv
、recvmsg
、accept
、connect
)
在程序中,我们可以根据系统调用的返回值以及errno来判断超时时间是否已到,进而决定是否开始处理定时任务。
下例为设置connect超时时间:
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
// 超时连接函数
int timeout_connect(const char* ip, int port, int time) {
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
assert(sockfd >= 0);
// 通过选项SO_RCVTIMEO和SO_ENDTIMEO所设置的超时事件类型是timeval,
// 这和select系统调用的超时时间参数类型相同
struct timeval timeout;
timeout.tv_sec = time;
timeout.tv_usec = 0;
socklen_t len = sizeof(timeout);
ret = setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, len);
assert(ret != -1);
ret = connect(sockfd, (struct sockaddr*)&address, sizeof(address));
if (ret == -1) {
// 超时对应的错误号是EINPROGRESS。
// 下面这个条件如果成立,我们就可以处理定时任务了
if (errno == EINPROGRESS) {
printf("connection timeout, process timeout logic\\n");
return -1;
}
printf("error occur when connecting to server\\n");
return -1;
}
return sockfd;
}
int main(int argc, char* argv[]) {
if (argc <= 2) {
printf("usage: %s ip_address port_number\\n", basename(argv[0]));
return 1;
}
const char* ip = argv[1];
int port = atoi(argv[2]);
int sockfd = timeout_connect(ip, port, 10);
if (sockfd < 0) {
return 1;
}
return 0;
}
【注】
timeval
:
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
其中tv_sec
为时间的秒部分,tv_usec
为时间的毫秒部分。
以上是关于使用socket选项SO_RCVTIMEO和SO_SNDTIMEO设置超时时间的主要内容,如果未能解决你的问题,请参考以下文章
通过 SO_RCVTIMEO 套接字选项在 Ruby 中设置套接字超时
如何在 C 中设置 SO_RCVTIMEO 选项仅用于读取而不用于接受
使用SO_REVTIMEO套接字选项为recvfrom设置超时
Linux(程序设计):60---定时机制之SO_RCVTIMEOSO_SNDTIMEO选项(附设置connect超时时间案例)