將乙個socket 設定成阻塞模式和非阻塞模式,使用fcntl方法,即:
設定成非阻塞模式:
先用fcntl的f_getfl獲取flags,用f_setfl設定flags|o_nonblock;
即:flags = fcntl(sockfd, f_getfl, 0); //獲取檔案的flags值。
fcntl(sockfd, f_setfl, flags | o_nonblock); //設定成非阻塞模式;
同時在接收和傳送資料時,需要使用msg_dontwait標誌
即:在recv,recvfrom和send,sendto資料時,將flag設定為msg_dontwait。
設定成阻塞模式:
先用fcntl的f_getfl獲取flags,用f_setfl設定flags&~o_nonblock;
即:flags = fcntl(sockfd,f_getfl,0); //獲取檔案的flags值。
fcntl(sockfd,f_setfl,flags&~o_nonblock); //設定成阻塞模式;
同時在接收和傳送資料時,需要使用阻塞標誌
即:在recv,recvfrom和send,sendto資料時,將flag設定為0,預設是阻塞。
在將socket設定成非阻塞模式後,每次的對於sockfd 的操作都是非阻塞的;
非阻塞模式下:
connect
=0 當返回0時,表示立即建立了socket鏈結,
<0 當返回-1時,需要判斷errno是否是einprogress(表示當前程序正在處理),否則失敗。
select監聽connect是否成功的例子,注意getsockopt驗證,因為三次握手的第三個ack有可能會丟失,但是客戶端認為鏈結已經建立:
int ret = ::connect(_socket_fd, add.addr(), add.length());
if(ret == 0)
else if(ret < 0 && errno == einprogress) //errno == einprogress表示正在建立鏈結
else if(retval == 0) // 超時
//將檢測到_socket_fd讀事件或寫時間,並不能說明connect成功
if(fd_isset(_socket_fd,&set))
if(error != 0) // 失敗
else}}
else
/*int error = 0;
socklen_t ilen = sizeof(error);
ret = getsockopt(fd,sol_socket,so_error,&error,&ilen);
if(ret < 0)
else if(error != 0 )
else
*/
recv 和 recvfrom
=0 當返回值為0時,表示對端已經關閉了這個鏈結,我們應該自己關閉這個鏈結,即close(sockfd)。另外因為非同步操作會用select或epoll做事件觸發,所以:
1、如果使用select,應該使用fd_clr(sockfd,fd_set)將sockfd清除掉,不再監聽。
2、如果使用epoll,系統會自己將sockfd清除掉,不再進行監聽。
>0 當返回值大於0 且 小於sizeof(buffer)時,表示資料肯定讀完。(如果等於sizeof(buffer),可能有資料還沒讀,應該繼續讀,不可能有大於)
<0 當返回值小於0,即等於-1時,分情況判斷:
1、如果 errno 為 eagain 或 ewouldblock
表示暫時無資料可讀,可以繼續讀,或者等待epoll或select的後續通知。(eagain,ewouldblock產生的
原因:可能是多程序讀同乙個sockfd,可能乙個程序讀到資料,其他程序就讀取不到資料(類似驚群效應),當然
單個程序也可能出現這種情況。對於這種錯誤,不需用close(sockfd)。可以等待select或epoll的下一次觸發,
繼續讀。)
2、如果 errno 為 eintr
表示被中斷了,可以繼續讀,或者等待epoll或select後續的通知。
否則,真的是讀取資料失敗。(此時應該close(sockfd))
send和sendto
返回值是實際傳送的字元數,因為我們知道要傳送的總長度,所以,如果沒有傳送完,我們可以繼續傳送。
<0 當返回值為 -1 時, 我們需要判斷 errno:
1、如果errno為 eagain 或 ewouldblock ,表示當前緩衝區寫滿,可以繼續寫,
或者等待epoll或select的後續通知,一旦有緩衝區,就會觸發寫操作,這個也是經常利用的乙個特性。
2、如果errno為eintr ,表示被中斷了,可以繼續寫,或者等待epoll或select的後續通知。
否則真的出錯了,即errno不為eagain或ewouldblock或eintr,此時應該close(sockfd)
>=0 >=0且不等於要求傳送的長度,應該繼續send,如果等於要求傳送的長度,傳送完畢。
connect設定連線超時
庖丁解牛 connect timeout 帶超時的connect 方法中已執行connect fd 檔案描述符 addr 位址結構體指標 wait seconds 等待超時秒數,如果為0表示不檢測超時 成功返回0.失敗返回 1,超時返回 1並且errno etimedout int connect ...
C socket 關於connect超時設定
使用阻塞的socket,可以設定讀寫超時,struct timeval tv timeout tv timeout.tv sec 60 tv timeout.tv usec 0 if setsockopt sockfd,sol socket,so sndtimeo,void tv timeout,s...
accept與connect的超時設定
connect超時 我們都知道,connect對應與三次握手中的第一次傳送syn,而對待伺服器的ack,如果伺服器沒有啟動伺服器,有些機器會立刻返回乙個rst表示伺服器拒絕,從而connect失敗,但又些伺服器為了防止攻擊,什麼也不傳送,直至客戶端connect超時,而這一時間又75s,對於客戶端來...