幾天前在博問中看到一個C# Socket問題,就想到筆者2004年做的一個省級交通流量接收伺服器項目,當時的基本求如下:
接收自動觀測裝置通過無線網卡、Internet和Socket上報的交通量資料包 全年365*24啟動並執行自動觀測裝置5分鐘上報一次觀測資料,每筆記錄約2K大小 規劃全省將有100個左右的自動觀測裝置(截止2008年10月還只有30個)
當時,VS2003才發布年多,筆者也是接觸C#不久。於是Google了國內國外網,希望找點應用C#解決Socket通訊問題的思路和代碼。最後,找到了兩篇協助最大的文章:一篇是國人寫的Socket接收器架構,應用了獨立的用戶端Socket會話(Session)概念,給筆者提供了一個接收伺服器的總體架構思路;另一篇是美國人寫的,提出了多線程、分段接收資料包的技術方案,描述了多線程、非同步Socket的許多實現細節,該文堅定了筆者採用多線程和非同步方式處理Socket接收器的技術路線。
具體實現和測試時筆者還發現,在Internet環境下的Socket應用中,需要系統有極強的容錯能力:沒有辦法控制異常,就必須允許它們存在(附加原始碼中可以看到,try{}catch{}語句較多)。對此,筆者設計了一個專門的檢查和清理線程,完成無效或逾時會話的清除和資源釋放工作。
依稀記得,國內架構作者的名稱空間有ibm,認為是IBM公司職員,通過郵件後才知道其人在深圳。筆者向他請教了幾個問題,相互探討了幾個技術關鍵點。可惜,現在再去找,已經查不到原文和郵件了。只好藉此機會,將本文獻給這兩個素未謀面的技術高人和同行,也盼望拙文或源碼能給讀者一點有用的啟發和協助。
1、主要技術思路
整個系統由三個核心線程組成,並由.NET線程池統一管理:
偵聽用戶端串連請求線程:ListenClientRequest(),迴圈偵聽用戶端串連請求。如果有,檢測該用戶端IP,看是否是同一觀測裝置,然後建立一個用戶端TSession對象,並通過Socket非同步呼叫方法BeginReceive()接收資料包、EndReceive()處理資料包 資料包處理線程:HandleDatagrams(),迴圈檢測資料包隊列_datagramQueue,完成資料包解析、判斷類型、儲存等工作 用戶端狀態檢測線程:CheckClientState(),迴圈檢查用戶端工作階段表_sessionTable,判斷會話對象是否有效,設定逾時會話關閉標誌,清楚無效會話對象及釋放其資源 2、主要類簡介
系統主要由3個類組成:
TDatagramReceiver(資料包接收伺服器):系統的核心進程類,建立Socket串連、處理與儲存資料包、清理系統資源,該類提供全部的public屬性和方法 TSession(用戶端工作階段):由每個用戶端的Socket對象組成,有自己的資料緩衝區,清理線程根據該對象的最近會話時間判斷是否逾時 TDatagram(資料包類):判
斷資料包類別、解析資料包
3、關鍵函數和代碼
下面簡介核心類TDatagramReceiver的關鍵實現代碼。