這幾天發現乙個現象,客戶端正常連線伺服器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 是我們常用的一種比較靠譜...