1. 程式人生 > >boost庫在工作(33)網路服務端之三

boost庫在工作(33)網路服務端之三

在這個例子裡,表示伺服器與一個客戶端的溝通渠道,就是一個連線,封裝為類CConnect。它是當伺服器接收到一個客戶端連線請求之後建立的,主要用來就是管理這個連線的生命週期,以及資料的接收和傳送。從生命週期上來說,當一個連線建立時就旦生了,那什麼時候死亡呢?在這個類的設計上是非常優秀,非常巧妙的,因為它不會為多生存一點時間而存在,也不會提前死掉而導致非法的記憶體訪問。有這樣的特性,主要是得益於它繼承類enable_shared_from_this< CConnect >,這個類enable_shared_from_this的魔力,就是為了在類內部函式使用shared_ptr,可以維護類的例項不至於失去控制,導致提前死亡。也許你會說,在類裡內部直接使用shared_ptr< CConnect >(this)進行強制轉換,不就是一個智慧指標了嗎?可是在shared_ptr這樣的智慧指標是不能進行強制轉換,因為強制轉換並不能增加類物件的生命長度。也許你會說,還有別的方法,在類裡增加一個shared_ptr< CConnect >成員變數,這樣可以儲存起來了,就達到生命週期的延長了。但這個方案雖然可以物件生命週期變長了,但也導致物件永遠刪除不了,這時,你也應想起前面學習過的shared_ptr智慧指標時的一大缺陷,就是不能迴圈地引用。因此,需要使用weak_ptr智慧指標做為成員變數,這樣就沒有這個問題了,這就是enable_shared_from_this所實現的方案,這就是為什麼要繼承enable_shared_from_this的原因。這樣就可以解決智慧指標在類內部引用的情況,但也有一個限制的,就是不能在這個類的建構函式裡使用shared_from_this(),因為在建構函式裡還沒有真正建立shared_ptr,這時就去使用,顯然是過早了。

有了這個魔法類之後,就可讓物件的生命週期從一個區域性作用域裡轉換到另外一個地方,比如在伺服器接收到連線時呼叫HandleAccept函式,緊跟著呼叫CConnect的Start函式,在這個函式就呼叫了shared_from_this()函式,這樣就讓CConnect物件在區域性作用域快要結束之時,再給它增加了生命,因此CConnect物件就可以在每次收到資料或傳送資料時,都可以決定是否還要繼續生存下去,都是通過呼叫shared_from_this()函式來實現的。這樣當連接出錯時,不再去呼叫shared_from_this()函式,導致這個物件生存期到了,就自動刪除,達到釋放資原的目標。

從這個例子裡,不但學習到網路伺服器怎麼樣接收客戶端的連線,也學習到在類成員函式裡維持一個共享智慧指標的生存下去的方法,這樣不僅讓管理記憶體更簡單,並且讓資源的利用率達到極點,完全是按需分配,不早也不遲,何樂而不為。