.NET 4.0網路開發入門之旅——
與Socket的“再次見面”
註:
這是一個針對
網路開發領域初學者
的系列文章,可作為《.NET 4.0 物件導向編程漫談
》一書的擴充閱讀,寫作過程中我假設讀者可以對照閱讀此書的相關章節,不再浪費筆墨重複介紹相關的內容。
對於其他類型的讀者,除非您已經有相應的.NET 技術背景與一定的開發經驗,否則,閱讀中可能會遇到困難。
我希望這系列文章能讓讀者領略到網路開發的魅力!
另外,這些文章均為本人原創,請讀者尊重作者的勞動,我允許大家出於知識共用的目的自由轉載這些文章及相關樣本,但未經本人許可,請不要用於商業盈利目的。
本文如有錯誤,敬請回貼指正。
謝謝大家!
金旭亮
=================================================
點擊以下連結閱讀本系列前面的文章:
《
開篇語——
無網不勝》
《
IP知多少》
《我在“網” 中央
》
《與Socket的第一次“約會”
》
=================================================
前一篇文章介紹了與Socket的第一次“約會”經曆,看來雙方的第一印象不錯,不然讀者也不會做出一個“繼續交往”的決定,並繼續閱讀本篇文章了。 :)
在這篇文章中,計劃介紹兩方面的內容:
Socket的串連請求隊列和如何開發“一問一答”的網路應用程式。
1 Socket的“串連請求隊列”
在現實生活中,一名品貌俱佳的女孩總是不乏追求者,人們會打趣地說“她的追求者有一個班”,這樣的一個女孩,在同一時間段內收到多個約會請求實在是太常見的事,當然,到底接受誰的約會邀請,就要看她中意誰了。
類似地,當一個綁定到特定終結點的Socket對象開始“監聽(Listen)”時,完全有可能有多個用戶端向此Socket同時發出多個串連請求,Socket對象必須決定如何處理這些串連請求。
為了方便處理,作業系統也會給每個正在監聽的Socket分配一個“串連請求隊列”,將收到的用戶端串連請求追加到此隊列中:
圖 1
由於網路伺服器上可能同時會有多個Socket同時監聽,我們應該給每個Socket對象分配一個 “適當容量”的隊列,以避免過多地佔用系統資源,讓網路伺服器能服務更多的線上使用者。
請求隊列的容量由Socket.Listen方法的參數backlog確定:
public void Listen(int backlog
);
例如,以下代碼指定newSocket對象最多隻能接收10個串連請求:
newsock.Listen(10
);
更詳細地說,如果newSocket對象正在忙於處理某個串連請求時,作業系統又接收到了多個嘗試串連此newSocket對象的請求,作業系統會把這些請求追加到newSocket對象所關聯的請求隊列中。
newSocket對象處理完當前串連之後,它再從關聯的請求隊列中取出一個處理。
一個有趣的問題是:如果某一時間段內串連請求很多,請求隊列“放不下”怎麼辦?
請看樣本解決方案ConnectionQueueDemo。這個解決方案中的MyServerApp項目與前一講
中的完全一樣,也是接收並顯示用戶端發來的一句“問好”訊息之後就斷開與此用戶端的串連。
為了直觀地體現串連請求隊列的特性,MyServerApp項目有意識地指定一個容量為“1”的請求隊列:
newsock.Listen(1);
在用戶端項目MyClientApp2中,建立10個線程,每個線程都建立一個Socket對象並嘗試著串連MyServerApp程式(圖 2)。
圖 2
我們看到了非常著名的“目標電腦積極拒絕……”的資訊,它是由以下這句英文直譯過來的:
…… the target machine actively refused it ……
就漢語來說,這明顯是一個病句,什麼叫“積極拒絕”?難道還有“消極拒絕”?
由此可見負責漢化Windows的程式員要不是“語文”學得不太好,要不就是“過於死板”了,個人覺得,此處意譯為以下這句更好:
嘗試串連的電腦拒絕了串連請求。
從樣本中我們可以得到結論:
當嘗試串連的用戶端發來的串連請求數目過大,超過了服務端Socket的串連請求隊列容量時,未能進入隊列的請求將會被丟棄,而用戶端將會得到一個代碼為10061的SocketException。 用戶端可以捕獲此異常,等待一定的時間再嘗試串連。
2 開發“一問一答”的網路應用程式
在各種網路應用程式中,“一問一答”可以說是最常見的一種類型。基於Socket實現這種類型的網路應用程式是非常簡單的:
在服務端與用戶端配套使用Send和Receive方法,只要傳送的資料不超過緩衝區的大小限制,就可以實現“一問一答”的標準C/S架構程式。
請看樣本解決方案EchoServiceDemo(圖 3):
圖 3
EchoServiceDemo樣本沒什麼複雜的,大家看看樣本源碼就清楚了。
看懂源碼後,請讀者做做以下實驗:
(1)先運行服務端程式EchoServiceApp,然後,運行用戶端程式EchoServiceClientApp串連上服務端,與EchoServiceApp進行交談,注意不要輸入“exit”命令退出。
(2)再運行EchoServiceClientApp的另一個執行個體,嘗試串連EchoServiceApp,發生了什嗎?
(3)運行EchoServiceClientApp的第3個執行個體,嘗試串連EchoServiceApp,又發生了什嗎?
你能利用已經掌握的知識解釋發生這些現象的原因嗎?從這個實驗中,您體會到了什嗎?總結出來了哪些經驗?
進一步地,讀者現在能解決以下這個問題嗎?
你能想辦法修改EchoServiceApp源碼,讓它同時可以服務多個用戶端應用程式嗎?
提示:
(1)在EchoServiceApp程式中為每個用戶端串連建立一個獨立的線程,在此線程中完成“一問一答”的工作。
(2)感到困難的讀者請參看《.NET 4.0物件導向編程漫談》,系統地學習第16章《多線程開發技術基礎》。
此處只是介紹了開發“一問一答”的網路應用程式的最基礎開發技巧,其實,這其中還有許多需要注意的“陷阱”,下一講將介紹Socket編程中最大的“陷阱”--緩衝區問題,並開發第一個真正有點實用價值的網路應用程式--網路四則運算計算機。
========================================
點擊下載樣本源碼
(部落格園的下載連結:http://files.cnblogs.com/bitfan/AskAndAnswerSourceCode.rar
)