C++自定义connect超时时间——信号处理法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/89429415

一 代码

#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>
#include <signal.h>

#define BUFFER_SIZE 512



void u_alarm_handler(int n)
{
    printf("alarm:-----------connect timeout----------\n");
}

int main( int argc, char* argv[] )
{

    char ip[]="192.168.0.111"; //本机的ip是192.168.0.110,192.168.0.111并不存在
    int port = 13334;

    struct sockaddr_in server_address;
    bzero( &server_address, sizeof( server_address ) );
    server_address.sin_family = AF_INET;
    inet_pton( AF_INET, ip, &server_address.sin_addr );
    server_address.sin_port = htons( port );

    int sock = socket( PF_INET, SOCK_STREAM, 0 );
    assert( sock >= 0 );



    int old_option = fcntl( sock, F_GETFL );
    printf("noblock: %d\n", old_option & O_NONBLOCK); //0 is block mode


    struct  timeval tv1, tv2;
    gettimeofday(&tv1, NULL);


    sigset(SIGALRM, u_alarm_handler);
    alarm(1);//设置1秒超时
    int ret = connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) );
    alarm(0);
    sigrelse(SIGALRM);


    
    printf("connect ret code is: %d\n", ret);
    if (  ret == 0 )
    {
        printf("call getsockname ...\n");
        struct sockaddr_in local_address;
        socklen_t length;
        int ret = getpeername(sock, ( struct sockaddr* )&local_address, &length);
        assert(ret == 0);
        char local[INET_ADDRSTRLEN ];
        printf( "local with ip: %s and port: %d\n",
            inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );


        char buffer[ BUFFER_SIZE ];
        memset( buffer, 'a', BUFFER_SIZE );
        send( sock, buffer, BUFFER_SIZE, 0 );
    }
    else if (ret == -1)
    {
        gettimeofday(&tv2, NULL);
        suseconds_t msec = tv2.tv_usec - tv1.tv_usec;
        time_t sec = tv2.tv_sec - tv1.tv_sec;
        printf("time used:%d.%fs\n", sec, (double)msec / 1000000 );

        printf("connect failed...\n");
        if (errno == EINPROGRESS)
        {
            printf("unblock mode ret code...\n");
        }
    }
    else
    {
        printf("ret code is: %d\n", ret);
    }


    close( sock );
    return 0;
}

二 运行

[root@localhost test]# g++ test.cpp -o test
[root@localhost test]# ./test
noblock: 0
alarm:-----------connect timeout----------
connect ret code is: -1
time used:1.0.000526s
connect failed...

三 说明

代码中,套接字依然是阻塞套接字。首先定义一个中断信号处理函数u_alarm_handler,用于超时后报警处理,然后定义1个1秒定时器,执行connect,当系统connect成功时,则系统正常执行下去;如果connect不成功阻塞在这里,则超过定义的1秒后,系统会产生一个信号,触发执行u_alarm_handler函数,当执行完u_alarm_handler后,程序继续从connect的下面一行执行下去。

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/89429415
今日推荐