用完成埠開發大響應規模的Winsock應用程式(2) (轉)

gugu99發表於2008-08-07
用完成埠開發大響應規模的Winsock應用程式(2) (轉)[@more@]

NT和的套接字架構

對於開發大響應規模的Winsock應用而言,對和Windows 2000的套接字架構有基本的瞭解是很有幫助的。

與其它型別操作不同,Windows NT和Windows 2000的傳輸沒有一種風格像套接字那樣的、可以和應用程式直接交談的介面,而是採用了一種更為底層的,叫做傳輸程式介面(Transport Interface,TDI)。Winsock的核心驅動程式負責連線和緩衝區管理,以便嚮應用程式提供套接字模擬(在AFD.SYS中實現),同時負責與底層傳輸驅動程式對話。

誰來負責管理緩衝區?

正如上面所說的,應用程式透過Winsock來和傳輸協議驅動程式交談,而AFD.SYS負責為應用程式進行緩衝區管理。也就是說,當應用程式send()或Wend()來傳送資料時,AFD.SYS將把資料複製進它自己的內部緩衝區(取決於SO_SNUF設定值),然後send()或WSASend()函式立即返回。也可以這麼說,AFD.SYS在後臺負責把資料傳送出去。不過,如果應用程式要求發出的資料超過了SO_SNDBUF設定的緩衝區大小,那麼WSASend()函式會阻塞,直至所有資料傳送完畢。

從客戶端接收資料的情況也類似。只要不用從應用程式那裡接收大量的資料,而且沒有超出SO_RCVBUF設定的值,AFD.SYS將把資料先複製到其內部緩衝區中。當應用程式呼叫recv()或WSARecv()函式時,資料將從內部緩衝複製到應用程式提供的緩衝區。

多數情況下,這樣的架構執行良好,特別在是應用程式採用傳統的套接字下非重疊的send()和receive()模式編寫的時候。不過程式設計師要小心的是,儘管可以透過setsockopt()這個API來把SO_SNDBUF和SO_RCVBUF選項值設成0(關閉內部緩衝區),但是程式設計師必須十分清楚把AFD.SYS的內部緩衝區關掉會造成什麼後果,避免收發資料時有關的緩衝區複製可能引起的系統崩潰。

舉例來說,一個應用程式透過設定SO_SNDBUF為0把緩衝區關閉,然後發出一個阻塞send()呼叫。在這樣的情況下,系統核心會把應用程式的緩衝區鎖定,直到接收方確認收到了整個緩衝區後send()呼叫才返回。似乎這是一種判定你的資料是否已經為對方全部收到的簡潔的方法,實際上卻並非如此。想想看,即使遠端TCP通知資料已經收到,其實也根本不代表資料已經成功送給客戶端應用程式,比如對方可能發生資源不足的情況,導致AFD.SYS不能把資料複製給應用程式。另一個更要緊的問題是,在每個執行緒中每次只能進行一次傳送呼叫,極其低下。

把SO_RCVBUF設為0,關閉AFD.SYS的接收緩衝區也不能讓得到提升,這隻會迫使接收到的資料在比Winsock更低的層次進行緩衝,當你發出receive呼叫時,同樣要進行緩衝區複製,因此你本來想避免緩衝區複製的陰謀不會得逞。

現在我們應該清楚了,關閉緩衝區對於多數應用程式而言並不是什麼好主意。只要要應用程式注意隨時在某個連線上保持幾個WSARe重疊呼叫,那麼通常沒有必要關閉接收緩衝區。如果AFD.SYS總是有由應用程式提供的緩衝區可用,那麼它將沒有必要使用內部緩衝區。

高效能的應用程式可以關閉傳送緩衝區,同時不會損失效能。不過,這樣的應用程式必須十分小心,保證它總是發出多個重疊傳送呼叫,而不是等待某個重疊傳送結束了才發出下一個。如果應用程式是按一個發完再發下一個的順序來操作,那浪費掉兩次傳送中間的空檔時間,總之是要保證傳輸驅動程式在傳送完一個緩衝區後,立刻可以轉向另一個緩衝區。

(譯者) 劉西齊 to:sickid10001@21cn.com">sickid10001@21cn.com


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1008663/,如需轉載,請註明出處,否則將追究法律責任。

相關文章