版权声明:本文为博主原创文章,未经博主允许不得转载。 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的下面一行执行下去。