Linux(服务器编程):27---定时机制之SO_RCVTIMEO、SO_SNDTIMEO选项(附设置connect超时时间案例)

  • Linux提供了三种定时方法,它们是:
    • socket选项SO_RCVTIMEO和SO_SNDTIMEO:本文要介绍的
    • SIGALRM信号,参见文章:https://blog.csdn.net/qq_41453285/article/details/103719025
    • I/O复用系统调用的超时参数,参见文章:https://blog.csdn.net/qq_41453285/article/details/103719077
  • Linux套接字超时介绍也可以参见这一篇文章的介绍:https://blog.csdn.net/qq_41453285/article/details/89792190

一、SO_RCVRIMEO选项、SO_SNDTIMEO选项概述

  • 这两个选项的介绍可以参见文章:
    • https://blog.csdn.net/qq_41453285/article/details/89532613
    • https://blog.csdn.net/qq_41453285/article/details/89536443
  • SO_RCVTIMEO:设置socket接收数据超时时间
  • SO_SNDTIMEO:设置socket发送数据超时时间
  • 注意,访问它们的getsockopt和setsockopt函数的参数是指向timeval结构的指针,与select所用参数相同。这可让我们用秒数和微秒数来规定超时。我们通过设置其值为0s和0µs来禁止超时。默认 情况下这两个超时都是禁止的
  • 这两个选项可以设置于以下的系统调用:
    • 输入函数:read、readv、recv、recvfrom和recvmsg
    • 输出函数:write、writev、send、sendto和sendmsg
    • accept、connect
  • 超时后的行为:有些系统调用在下表未给出,但errno都是相同的

Linux(服务器编程):27---定时机制之SO_RCVTIMEO、SO_SNDTIMEO选项(附设置connect超时时间案例)_第1张图片

二、演示案例(设置connect超时时间)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


int timeout_connect(const char* ip,int port,int time);

int main(int argc,char* argv[])
{    
    if(argc!=3){
        printf("usage:./%s [server ip] [server port]\n",basename(argv[1]));
        exit(EXIT_FAILURE);
    }

    const char* ip;
    int client_fd,port,time;

    ip=argv[1];
    port=atoi(argv[2]);
    time=10;

    client_fd=timeout_connect(ip,port,time);
    if(client_fd==-1)
    {
        close(client_fd);
        exit(EXIT_FAILURE);
    }

    printf("connect success!\n");
    
    close(client_fd);
    exit(EXIT_SUCCESS);
}

int timeout_connect(const char* ip,int port,int time)
{
    int client_fd;

    //创建套接字
    if((client_fd=socket(AF_INET,SOCK_STREAM,0))==-1){
        perror("socket");
        return -1;
    }

    //设置SO_SNDTIMEO超时选项
    struct timeval timeout;
    timeout.tv_sec=time;
    timeout.tv_usec=0;
    socklen_t time_len=sizeof(timeout);
    
    if(setsockopt(client_fd,SOL_SOCKET,SO_SNDTIMEO,&timeout,time_len)==-1){
        perror("setsockopt");
        return -1;
    }
    
    //初始化服务器地址
    struct sockaddr_in server_address;
    bzero(&server_address,sizeof(server_address));
    server_address.sin_family=AF_INET;
    server_address.sin_port=htons(port);
    if(inet_pton(AF_INET,ip,&server_address.sin_addr)==-1){
        perror("inet_pton");
        return -1;
    }

    //连接服务端
    printf("wait connect......\n");
    int connect_ret_value;
    if((connect_ret_value=connect(client_fd,(struct sockaddr*)&server_address,sizeof(server_address)))==-1){
        if(errno==EINPROGRESS){
            printf("connect timeout!\n");
            return -1;
        }
        perror("connect");
        return -1;
    }

    return client_fd;
}

代码测试

  •  我们使用这个程序去连接服务模拟工具,服务端工具没开启监听的时候,我们的程序连接超时

Linux(服务器编程):27---定时机制之SO_RCVTIMEO、SO_SNDTIMEO选项(附设置connect超时时间案例)_第2张图片

  • 当我们将服务端工具开启监听之后,我们的程序连接成功

Linux(服务器编程):27---定时机制之SO_RCVTIMEO、SO_SNDTIMEO选项(附设置connect超时时间案例)_第3张图片

你可能感兴趣的:(Linux(服务器编程))