socket connec連接超時處理

最近把win32下的網關服務轉到linux平臺時遇到connect連接超時問題,經過多方收集資料簡單整理下方便以後查找socket <wbr>connec連接超時處理

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){
             

發佈了79 篇原創文章 · 獲贊 17 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章