最近把win32下的网关服务转到linux平台时遇到connect连接超时问题,经过多方收集资料简单整理下方便以后查找
linux或者win32控制台程序中connect函数默认是阻塞的,成功则返回0,失败返回-1,错误码可以用函数GetLastError获得。如果连接一个打开的服务器一般回立即返回并且成功连接socket连接,如果连接一个存在但是没有开启的服务器会阻塞一段时间(不会太长)然后返回-1. 还有一种就是连接一个网内不存在的服务器,比如192.168.0.256。这时就会阻塞很长的时间大概20+秒。这篇文章最初就是为了解决这个问题而写的。
废话不多说了进入正题(读者:你的废话已经够多了)。。。。。。。
为了处理connect的连接超时可以在调用socket函数之后使用fcntl函数将sock描述符设置为非阻塞,然后进行连接(connect),会立即返回-1,判断错误码是否等于EINPROGRESS,也就是判断连接是不是正在进行中,如果是那么通过select查询在一段时间内该描述符是否可写来判断连接是成功还是失败。如果错误码不等于EINPROGRESS那么连接失败。下面给出linux和window具体实现方法
WINDOWS:
int main()
{
SOCKET sock;
SOCKADDR_IN addr;
fd_set r;
unsigned long ul = 1;
struct timeval timeo = {3, 0};
//创建socket描述符
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
printf("socket fail");
return -1;
}
//设置阻塞
if(ioctlsocket(sock, FIONBIO, (unsigned long*)&ul) == SOCKET_ERROR)
{
printf("ioctlsocket fail");
return -1;
}
//初始化addr。。。。。。
//发起连接
if(connect(sock, (const struct sockaddr*)addr, sizeof(addr)) == SOCKET_ERROR)
{
FD_ZERO(&r);
FD_SET(scok, &r);
if(select(0, &r, 0, 0, &timeo) <= 0)) //需要注意select函数第一个参数在winsock被忽略了,
//在linux必须是sock+1;
{
printf("connect fail");
return -1;
}
else
{
printf("connect success");
//to do
}
}
}
LINUX:(转自中关村 作者:天新网 http://server.zol.com.cn/127/1271166.html)
#include<stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>
int main(int argc,char*argv[])
{
int fd, retval;
structsockaddr_in addr;
structtimeval timeo={3, 0}; //初始化超时时间
socklen_t len=sizeof(timeo);
fd_set set;
fd =socket(AF_INET,SOCK_STREAM, 0);
if(argc== 4)
timeo.tv_sec=atoi(argv[3]);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)| O_NONBLOCK); //将fd设置为非阻塞
addr.sin_family=AF_INET;
addr.sin_addr.s_addr= inet_addr(argv[1]);
addr.sin_port=htons(atoi(argv[2]));
printf("%dn",time(NULL));
if(connect(fd,(structsockaddr*)&addr,sizeof(addr))== 0){
printf("connectedn");
return 0;
}
if(errno!= EINPROGRESS){
perror("connect");
return-1;
}
FD_ZERO(&set);
FD_SET(fd,&set);
retval = select(fd+ 1,NULL,&set,NULL,&timeo);
if(retval==-1){