設置connect的超時很簡單,CSDN上也有人提到過使用select,但卻沒有一個令人滿意與完整的答案。偶所講的也正是select函數,此函數集成在winsock1.1中,簡單點講,"作用使那些想避免在套接字調用過程中被鎖定的應用程序,采取一種有序的方式,同時對多個套接字進行管理"(《Windows網絡編程技術》原話)。使用方法與解釋請見《Windows網絡編程技術》。
在使用此函數前,需先將socket設置為非鎖定模式,這樣,在connect時,才會立馬跳過,同時,通常也會產生一個WSAEWOULDBLOCK錯誤,這個錯誤沒關系。再執行select則是真正的超時。
1 WSADATA wsd; 2 SOCKET cClient; 3 int ret; 4 struct sockaddr_in server; 5 hostent *host=NULL; 6 7 if(WSAStartup(MAKEWORD(2,0),&wsd)){ 8 return 0; 9 } 10 11 cClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 12 13 if(cClient==INVALID_SOCKET){ 14 return 0; 15 } 16 17 //set Recv and Send time out 18 int TimeOut=6000; //設置發送超時6秒 19 if(::setsockopt(cClient,SOL_SOCKET,SO_SNDTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){ 20 return 0; 21 } 22 TimeOut=6000;//設置接收超時6秒 23 if(::setsockopt(cClient,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut))==SOCKET_ERROR){ 24 return 0; 25 } 26 //設置非阻塞方式連接 27 unsigned long ul = 1; 28 ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul); 29 if(ret==SOCKET_ERROR) 30 return 0; 31 32 //連接 33 server.sin_family = AF_INET; 34 server.sin_port = htons(25); 35 server.sin_addr .s_addr = inet_addr((LPCSTR)pSmtp); 36 if(server.sin_addr.s_addr == INADDR_NONE){ 37 return 0; 38 } 39 40 connect(cClient,(const struct sockaddr *)&server,sizeof(server)); 41 42 //select 模型,即設置超時 43 struct timeval timeout ; 44 fd_set r; 45 46 FD_ZERO(&r); 47 FD_SET(cClient, &r); 48 timeout.tv_sec = 15; //連接超時15秒 49 timeout.tv_usec =0; 50 ret = select(0, 0, &r, 0, &timeout); 51 if ( ret <= 0 ) 52 { 53 ::closesocket(cClient); 54 return 0; 55 } 56 //一般非鎖定模式套接比較難控制,可以根據實際情況考慮 再設回阻塞模式 57 unsigned long ul1= 0 ; 58 ret = ioctlsocket(cClient, FIONBIO, (unsigned long*)&ul1); 59 if(ret==SOCKET_ERROR){ 60 ::closesocket (cClient); 61 return 0; 62 }
關鍵代碼段
1 struct timeval tv = {timeout, 0}; 2 setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); 3 //setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));//設置接收超時,不能對connect起作用
1.常用方法
設置socket非阻塞,之后使用select等設置超時時間
2.使用alarm信號量
需要注意:線程信號量掩碼是線程私有的,當指定進程遞交信號量時,操作系統會將信號量遞交至該進程中未屏蔽該信號量的所有線程中的隨機之一。見 man 7 signal:
A signal may be generated (and thus pending) for a process as a whole
(e.g., when sent using kill(2)) or for a specific thread (e.g., certain
signals, such as SIGSEGV and SIGFPE, generated as a consequence of exe-
cuting a specific machine-language instruction are thread directed, as
are signals targeted at a specific thread using pthread_kill(3)). A
process-directed signal may be delivered to any one of the threads that
does not currently have the signal blocked. If more than one of the
threads has the signal unblocked, then the kernel chooses an arbitrary
thread to which to deliver the signal.
皆抄襲自《TCP高效編程》
