本節來將客戶端的connect
阻塞式改為非阻塞式. 這樣可以同時向服務端發起多個連線並一起進行處理, 非阻塞connect
一般用來測試服務端的抗壓能力.
connect
設定為非阻塞之後會立即返回 設定errno為einprogress
錯誤, 表示連線操作正在進行中, 但是仍未完成連線; 同時tcp的三次握手操作繼續進行. 之後, 可以呼叫select
來檢查連線是否成功.
其非阻塞connect
有三種用途 :
可以在三路握手的同時做一些其它的處理. 這段時間可能幾毫秒但也可能幾百毫秒.
可以同時建立多個連線. 在web瀏覽器中很普遍.
可以使用select
(或者io復用其他函式) 來等待連線的完成, 因此可以給select
設定時間限制, 從而縮短connect
的超時時間. 畢竟大多數中,connect
的超時時間在75秒到幾分鐘之間. 我們就可以通過connect
非阻塞來設定更短的超時時間.
connect
的細節還有一些需要注意哦, 不然很容易處理錯誤 :
即使套介面是非阻塞的, 如果連線的伺服器在同一臺主機上, 那麼呼叫connect
建立連線時, 連線通常會立即建立成功.
源自berkeley 的實現 (和posix) 有兩條與 select 和非阻塞 connect 相關的兩條規則:
- 當連線建立成功時, 套介面描述符變成可寫;
- 當連線出錯時, 套介面描述符變成既可讀又可寫;
注意:當乙個套介面出錯時,它會被select呼叫標記為既可讀又可寫.
connect
沒有超時設定, 但是我們可以將其設定為非阻塞式, 由select
來設定超時即可. 在寫**時要注意上述的細節處理哦.
完整** :
客服端 : timeout_client.c
服務端 : service.c
客服端部分** :
// connect 超時封裝
inttimeout_connect
(int sockfd,
struct sockaddr *addr, socklen_t socklen,
int nsec)
// 本機連線, 會立即建立連線
if(ret ==0)
// rset : 用於判斷可讀; wset : 用於判斷可寫.
fd_set rset, wset;
fd_zero
(&rset)
;fd_set
(sockfd,
&rset)
; wset = rset;
tval.tv_sec = nsec;
tval.tv_usec =0;
if(select
(sockfd+1,
&rset,
&wset,
null
, nsec ?
&tval :0)
==0)// 可讀 | 可寫if(
fd_isset
(sockfd,
&rset)
||fd_isset
(sockfd,
&wset)
)else
done:
// sockfd 恢復到進函式進前的狀態. 因為只有 connect 需要非阻塞
fcntl
(sockfd, f_setfl, oldfd);if
(err)
return0;
}
函式中, 注意connect
返回0代表本機間能快速連線成功. 連線成功後需要將socket
恢復到最初的狀態, 在該封裝中我們只用關心非阻塞狀態.
關於connect
非阻塞還有乙個問題, 就是不可移植性. 下面我將移植的問題羅列出來.
出錯的套介面描述符,getsockopt
的返回值在 berkeley 的實現是返回0, 待處理的錯誤值儲存在errno中; 而 solaris 的實現是返回-1, 待處理的錯誤儲存在errno中.( 套介面描述符出錯時呼叫getsockopt的返回值不可移植)
有可能在呼叫select之前, 連線就已經建立成功, 而且對方的資料已經到來, 在這種情況下, 套介面描述符是既可讀又可寫;這與套介面描述符出錯時是一樣的.
那麼上述問題怎麼解決呢? 在我們判斷連線是否建立成功的條件不唯一時, 可用以下的方法來解決這個問題:
呼叫getpeername
代替getsockopt
.
如果呼叫getpeername
失敗,getpeername
返回 enotconn, 表示連線建立失敗, 必須以 so_error 呼叫 getsockopt 得到套介面描述符上的待處理錯誤.
呼叫read
, 讀取長度為0位元組的資料.
呼叫一次connect
. 它應該失敗, 如果錯誤errno = eisconn
, 就表示套介面已經建立, 而且第一次連線是成功的; 否則, 連線就是失敗的.
TCP的套接字
摘自 深入理解計算機網路 王達著 機械工業出版社 1.ipv4資料報頭部格式 2.ipv6資料報頭部格式 3.ipv4資料報的封裝與解封裝 4.ipv4資料報的分段與重組 5.arp協議報文格式及arp表 6.arp位址解析原理 7.icmp協議及報文格式 8.ipv6協議族的其它協議 9.tcp的...
TCP套接字程式設計
網路程式設計又稱為套接字程式設計,為了與遠端計算機進行資料傳輸,需要連線到網際網路,而程式設計中的 套接字 就是用來連線該網路的工具。它本身具有連線的含義,還可以表示為兩台計算機之間的網路連線。4.呼叫accept函式受理連線請求 基於tcp的服務端 客戶端 tcp伺服器端預設函式呼叫順序 sock...
TCP套接字程式設計
對於socket不理解的可以檢視 c語言通過socket程式設計實現tcp通訊,linux socket程式設計 socket詳解 先看看程式效果圖 提示如果伺服器,直接通過ctrl z關閉,這樣程式占用的位址不會釋放,需要以下操作 1.ps 檢視程序 2.kill 9 程式pid 強制殺死程序 服...