函数原型:
<pre name="code" class="cpp">#include <sys/socket.h>
int connect(int socket, const struct sockaddr *address,socklen_t address_len)
成功:返回0 失败:返回-1
1.如果没有设置O_NONBLOCK状态,并且不能立即建立连接,将一直阻塞。如果在此过程中被信号中断,connect将返回失败,并设置errno 为 EINTR,但连接请求此时不会退出,连接将会异步建立。
2.如果设置了O_NONBLOCK,并且不能立即简历连接,连接将返回失败,并设置errno 为EINPROGRESS,连接请求不会中断,连接将会异步建立。如果在连接没有建立完成的状态下重新调用connect连接同一个socket将返回失败,并设置errno 为EALREADY。
非阻塞connect成功或失败判断方式:
1.调用connect返回0,连接成功,返回。
否则
2.返回-1时,如果errno不等于EINPROGRESS,连接失败。
否则
3.通过select poll epoll监听描述符事件,比如select,如果select返回值<=0表示select失败或超时,连接失败。
或 描述符不可写,连接失败。(connect成功时,描述符可写;connect失败时,描述符可读可写)
4.通过getsockopt获取描述符上的错误,如果错误号不是0,表示连接失败。
否则
5.连接成功
部分源码示意:(摘自Linux高性能服务器编程)
// 设置非阻塞
int fdopt = setnonblocking( sockfd );
ret = connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) );
// 连接成功
if ( ret == 0 )
{
printf( "connect with server immediately\n" );
fcntl( sockfd, F_SETFL, fdopt );
return sockfd;
}
// 连接失败
else if ( errno != EINPROGRESS )
{
printf( "unblock connect not support\n" );
return -1;
}
fd_set readfds;
fd_set writefds;
struct timeval timeout;
FD_ZERO( &readfds );
FD_SET( sockfd, &writefds );
timeout.tv_sec = time;
timeout.tv_usec = 0;
// 监听描述符事件
ret = select( sockfd + 1, NULL, &writefds, NULL, &timeout );
// select错误或超时
if ( ret <= 0 )
{
printf( "connection time out\n" );
close( sockfd );
return -1;
}
// 描述符不可写
if ( ! FD_ISSET( sockfd, &writefds ) )
{
printf( "no events on sockfd found\n" );
close( sockfd );
return -1;
}
int error = 0;
socklen_t length = sizeof( error );
// 获取错误码
if( getsockopt( sockfd, SOL_SOCKET, SO_ERROR, &error, &length ) < 0 )
{
printf( "get socket option failed\n" );
close( sockfd );
return -1;
}
// 错误码不等于0,失败
if( error != 0 )
{
printf( "connection failed after select with the error: %d \n", error );
close( sockfd );
return -1;
}
// 连接成功
// TODO