一个简单实现非阻塞socket,超时响应并判断是否连接成功demo:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#define IPADDR "www.baidu.com"
#define PORT 80
int main()
{
struct addrinfo *res, hint;
fd_set rest, west;
int error;
socklen_t optlen = sizeof(error);
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_STREAM;
if (0 != getaddrinfo(IPADDR, NULL, &hint, &res)) {
goto err0;
}
int sock = socket(res->ai_family, res->ai_socktype, 0);
if (-1 == sock)
goto err1;
if(-1 == fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK))
goto err2;
struct sockaddr_in addr;
memset(&addr, 0 , sizeof(addr));
addr.sin_family = res->ai_family;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
int ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
printf("ret = %d,errno = %d\n",ret,errno);
if (-1 == ret && EINPROGRESS != errno)
goto err2;
/*添加select超时响应*/
FD_ZERO(&rest);
FD_ZERO(&west);
FD_SET(sock, &rest);
FD_SET(sock, &west);
struct timeval tempval;
tempval.tv_sec = 3;
tempval.tv_usec = 0;
int flag = select(sock+1, &rest, &west, NULL, &tempval);//监听套接的可读和可写条件
if(flag < 0)
{
printf("select error\n");
goto err2;
}
else
{
/*说明*/
/*在何时确认连接成功,第一种:可写不可读,第二种:可读可写,通过getsockopt获取
sock信息,返回值为0且返回错误值也为0的情况连接成功。
*/
if(!FD_ISSET(sock, &rest) && !FD_ISSET(sock, &west))
{
printf("connect no response\n");
goto err2;
}
else if(FD_ISSET(sock, &rest) && FD_ISSET(sock, &west))
{
flag = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &optlen);
if(flag == 0 && error == 0)
{
printf("connect success....\n");
}
else
{
printf("connect error....\n");
goto err2;
}
}
else if(!FD_ISSET(sock, &rest) && FD_ISSET(sock, &west))
{
printf("connect success....\n");
}
else
{
printf("connect error....\n");
goto err2;
}
}
close(sock);
freeaddrinfo(res);
return 0;
err2:
close(sock);
err1:
freeaddrinfo(res);
err0:
return 0;
}