如何解決Connect超時導致的阻塞問題

2021-07-09 14:52:29 字數 2407 閱讀 2515

這幾天發現乙個現象,客戶端正常連線伺服器connect顯然不會出現問題。

在異常情況下,如果是伺服器出現異常,connect能夠立即返回失敗;但是當客戶端出現異常的情況下,分為兩種情況:

一種是不插網線,客戶端沒有獲得ip位址,在這種情況下,connect也可以立即返回錯誤;

二是但是當客戶端插上網線,但是連線網路失敗,也就是說能夠獲取到ip位址,但是和伺服器是ping不通的。這種情況下connect就可能會發生阻塞,因為按照《unix 網路程式設計》中講解,connect的在進行三次握手,如果失敗情況,需要等待75s的超市時間的。

我們主要討論第二種情況如何解決,可以讓connect快速返回結果,不至於阻塞等待超長的時間。

如下是我的**

/******************************

* time out for connect()

******************************/

#include #include #include #include #include #include #include #include #include #include #include #define time_out_time 20 //connect超時時間20秒

bool setblockopt(int m_fd,bool blocked)

if(blocked)

else

if(fcntl(m_fd, f_setfl, flags) < 0)

#else

u_long ulvalue;

if(blocked)

else

int n = ioctlsocket(m_fd, fionbio, &ulvalue);

if (n != 0)

#endif

return true;

}int connectwithtimeout(int m_fd,int timeout)

if(m_fd < 0 && "" != m_ip && m_port >=0) }

if(m_fd < 0)

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = af_inet;

servaddr.sin_port = htons((unsigned short)m_port);

servaddr.sin_addr.s_addr = inet_addr(m_ip);

setblockopt(m_fd,false); //設定為非阻塞模式

if( (connectflag= connect(m_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)) }

else

timeval tm;

tm.tv_sec = timeout/1000;

tm.tv_usec = timeout%1000;

fd_set rest, west;

fd_zero(&rest);

fd_zero(&west);

fd_set(m_fd, &rest);

fd_set(m_fd, &west);

if( (selectflag = select(m_fd+1, &rest, &west, null, &tm)) > 0)

else

else

}} //如果套介面可寫不可讀,則鏈結完成

else if(fd_isset(m_fd, &west) && !fd_isset(m_fd, &rest))

}else if(selectflag == 0)

else

done:

setblockopt(m_fd,true);// 設定為阻塞模式

if(!ret)

return 0;

}int main(int argc,char* argv)

int sockfd = socket(af_inet, sock_stream, 0);

if(sockfd < 0)

if(connectwithtimeout(sockfd,atoi(argv[1])) == 0)

else

close(sockfd);

return 0;

}

原理很簡單,就是先把套接字設定為非阻塞,因為在非阻塞情況下,connect的結果是立即返回的,然後我們再使用select或者poll等機制來檢測套接字一定的時間,如果在超時時間內不可寫,則認為connect失敗,然後需要把套接字重新設定為阻塞,當然如果你不需要在阻塞模式下工作,可以不用設定。

如上,我們就可以對connect的超時進行可控。

如何解決Connect超時導致的阻塞問題

在異常情況下,如果是伺服器出現異常,connect能夠立即返回失敗 但是當客戶端出現異常的情況下,分為兩種情況 一種是不插網線,客戶端沒有獲得ip位址,在這種情況下,connect也可以立即返回錯誤 二是但是當客戶端插上網線,但是連線網路失敗,也就是說能夠獲取到ip位址,但是和伺服器是ping不通的...

如何解決MySQL連線超時關閉

最近做 有乙個站要用到web網頁採集器功能,當乙個php指令碼在請求url的時候,可能這個被請求的網頁非常慢慢,超過了mysql的 wait timeout時間,然後當網頁內容被抓回來後,準備插入到mysql的時候,發現mysql的連線超時關閉了,於是就出現了 mysql server has go...

php 訪問超時,php請求介面超時如何解決

http訪問 一般我們訪問http方式很多,主要是 curl,socket,file get contents 等方法。如果碰到對方伺服器一直沒有響應的時候,我們就悲劇了,很容易把整個伺服器搞死,所以在訪問http的時候也需要考慮超時的問題。curl 訪問http curl 是我們常用的一種比較靠譜...