43 TCP套接字之connect非阻塞

2021-09-21 18:13:57 字數 2728 閱讀 4846

本節來將客戶端的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 強制殺死程序 服...