最近把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){