大家都知道socket在接收報文時有兩種方式,一種方式是receive成為同步方式(這種方式的特點是自帶阻塞,至於阻塞的時長和機制還沒有弄清楚),還有一種是BeginReceive成為異步(這種方式的阻塞是可以根據我們的需要手動控制的),同步方式大家用得非常多,一般用於 對報文傳輸在時間上沒有嚴格要求的地方,最終只要保證所傳送的報文都能夠被接收到,不管是分幾次收到還是一次收入緩存,但同步方式在不給報文加入邊界標示 時是很容易出現socket粘包現象的,而且在同步方式的基礎上解決粘包的方法都很不理想。在這種情形下我們可以考慮使用異步方式。
今天這里我要說是異步方式,一般在對TCP傳輸過程中的分包有嚴格的要求時,我們都采用socket的異步方式,當然,異步方式相對同步方式在使用上略微復雜寫,這也是大多人不是在萬不得已的情況下不想使用它的願意之一吧。
相 對同步方式,異步方式會有一個回調函數的調用,當緩沖區接收到一個包后回調函數被調用(處於緩沖區數據的代碼一般都放置在回調函數中),回調函數被調用的 時候BeginReceive被阻塞,直到回調函數被執行完畢。(不過我在想,異步方式緩沖區收到一個包之前應該是按照IP包的包頭和包尾標志進行了處 理,而同步方式則略過了這個步驟,只要兩個包之間的間隔‘不太長’就把報文按照排隊的方式送入了緩沖區,導致發生粘包的問題,這個不太長究竟是多長我還沒 有弄清楚,也希望有高人能夠指點)
在微軟的文檔中是這樣描述的:
“Your callback method should implement the EndReceive method. When your application calls BeginReceive, the system will use a separate thread to execute the specified callback method, and will block on EndReceive until the Socket reads data or throws an exception.”
也就是說我們調用BeginReceive的時候,系統會幕后開啟一個獨立的線程,用以執行回調函數及對EndReceive的阻塞(block),直到EndReceive從socket的緩沖區中讀到數據或者socket引發異常。
換 句話說如果我們在回調函數還沒有被執行之前調用EndReceive則程序就被阻塞於此,直到獲得數據為止或引發異常。所以一般我們還是要通過回調函數來 調用EndReceive方法(我的理解,如果EndReceive沒有解除阻塞,則BeginReceive的緩沖區參數即socket的緩沖區無法繼 續獲取新的報文,或者說EndReceive的執行會導致緩沖區被清空)。