linux下socket的connect超時

代碼的流程是這樣的
1 建立一個socket
2 設置socket爲非阻塞
3 connect
4 把socket放到一個fd_set中
5 select 這個socket,監視可寫事件
6 判斷是否超時或者連接成功
   
代碼如下---------------------------------------------------------------------
struct sockaddr_in servAddr;
servAddr.sin_port = htons(port);
servAddr.sin_family = AF_INET;
inet_aton(servIp,&servAddr.sin_addr);
//設置socket爲非阻塞
unsigned long ul = 1;
int rm = ioctl(this->m_socket,FIONBIO,&ul);
if(rm == -1)
{
 //ioctl failed
 return -1;
}
if(connect(this->m_socket,(sockaddr*)&servAddr,sizeof(sockaddr)) == 0)
{
 //connect success
 return 0;
}

if(errno != EINPROGRESS)
{
 return -1;
}
log_debug("%s",strerror(errno));
//檢測socket是否可寫
fd_set writeSet,readSet;
FD_ZERO(&writeSet);
FD_SET(this->m_socket,&writeSet);
int num = select(this->m_socket+1, NULL, &writeSet,NULL,tv);
if(num > 0)
{
 if(FD_ISSET(this->m_socket,&writeSet))
 {
  //設置socket爲阻塞
  ul = 0;
  ioctl(this->m_socket,FIONBIO,&ul);
  return 0;
 }
}

首先說一下這段代碼的執行結果:當連接一個並不存在的socket時,select總是返回連接成功
 
按照這個流程,這段代碼的依據就是當非阻塞時,connect立刻返回-1,同時errno設置爲EINPROGRESS。然後再檢測socket是否可寫,如果可寫了,說明socket已經建立的連接,這個時候select的會在write fd_set中把socektfd置位,同時返回,這個時候判斷select的返回值和用FD_ISSET宏來判斷是否socketfd是否已經被置位來判斷是否連接成功。注意:所有的這一切都是建立在 “如果一個socket建立了連接,那麼這個socket是可寫的”,這看起來沒有錯,但是關鍵是,如果連接不成功,select是否會判斷socket爲可寫的呢?我們知道,當連接被關閉時,select仍然判斷socket是可讀的。難道即使socket連接不成功,select仍然返回
可寫嗎?經過試驗,真的是這樣的。所以,上面的代碼如果在異常情況下仍然正常工作,在select返回時須作如下修改:
if(FD_ISSET(this->m_socket,&writeSet))
{
 int error = 0;
 int errLen = sizeof(error);
 if(getsockopt(this->m_socket,SOL_SOCKET,SO_ERROR,&error,(socklen_t*)&errLen) < 0)
 {
  return -1;
 }
 if(error != 0)
 {//當error等於0的時候才說明連接成功
  return -1;
 }
 //設置socket爲阻塞
 ul = 0;
 ioctl(this->m_socket,FIONBIO,&ul);
 return 0;
}

//以上的代碼中的思想我正在用,但真的沒起到連接超時的效果,一旦連接不成功還是回立即返回的.還有socket在阻塞的情況下,connect()也沒有阻塞,也是立即返回的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章