使用socket选项SO_RCVTIMEO和SO_SNDTIMEO设置超时时间

socket选项SO_RCVTIMEOSO_SNDTIMEO,他们分别 用来设置socket接受 / 发送数据超时时间。
因此,这两个选项仅对数据接收和发送相关的socket专用系统调用有效(sendsendmsgrecvrecvmsgacceptconnect

在程序中,我们可以根据系统调用的返回值以及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为时间的毫秒部分。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值