又一個對Socket的封裝庫。 http://blog.donews.com/dgsheng/archive/2006/03/16/771372.aspx
ACE將網絡編程進行了模式化,以便你不必每次都重復相同的代碼。
網絡編程需要處理的事情多括中斷,并發,多線程等,程序格式相對固定,但是健壯的網絡程序則相對復雜。為了處理這些情形,ACE內建了幾個網絡編程的模式。
最基本的模式當然是直接使用sock進行單客戶單服務器單線程的一對一模型,這種模式相對簡單,也和ACE關系不大,但是這樣編寫的程序不能處理并發的情況,可用性很差或者說基本不具有可用性。
最簡單的處理并發但是卻使用單線程的框架在ACE中稱為Reactor框架,在這種框架下,Reactor扮演了協調員的角色,應用程序編制者需要首先寫好各種各樣的事件處理程序,然后在Reactor中進行登記,Reactor以阻塞的方式同時監視所有可能發生的事件,并且在相應的事件發生的時候調用對應的處理過程。這種框架解決了在單線程的前提下解決了并發,但是存在一定的問題,如果某個事件執行過程過長,則可能導致Reactor漏過某些事件。
另外一種單線程處理并發的模式稱為異步I/O的Proactor模式,這種模式和前面介紹的Reactor模式其實區別不大,唯一的區別之處在于,Server類在對從網絡上收到的消息進行處理的時候,后者并不直接讓處理器處理收到的消息,而是首先將消息轉換為一個消息塊結構(ACE_Message_Block,通過this->reader_.read函數),然后再讓相應的處理函數處理已經接收好的消息塊結構。
比較一下Reactor框架和Proactor框架,前者的執行流程是: 監視事件->調用事件處理過程->繼續監視事件。 后者的執行流程是: 監視事件->產生消息->處理消息->釋放消息->繼續監視事件。這兩種不同的框架在引入各自的多線程概念以后,就衍生出不同的多線程框架。
前面說過,使用多線程進行網絡編程也有兩種框架,半同步/半異步框架和領導者/跟隨者框架。前者對應的是Proactor框架,后者對應的是Reactor框架。所謂半同步或者半異步框架,執行的流程是:主線程負責 監視事件->產生消息->放入消息隊列->監視事件,工作線程則負責從獲取消息->處理消息->從消息隊列獲取另外一個消息。 這種框架的優勢在于,由于構造消息并且將其放入消息隊列的時間是可以控制的,因此,可以很好的處理網絡峰值的情況,即使出現很高的峰值,也不會造成消息的遺漏,但是由于消息存在一個入隊列,出隊列的過程,因此性能相較另外一種模型,理論上更差。
后者則是一種相對更復雜的模型,在線程池中只有一個線程是領導者線程,其他為跟隨者線程,領導者線程監視事件,在事情發生的時候,首先尋找另外一個線程變為領導者,然后自己再處理事件,處理完成以后,首先嘗試再次成為領導者,如果嘗試失敗(另外一個線程已經成為領導者),則自己變成跟隨者。 這種模型基于Reactor模型,沒有消息隊列的概念,由于不存在出入隊列的過程,性能相對前者理論上更好。但是如果存在很高的網絡蜂擁,則可能由于所有的線程都在處理各自的事件,導致沒有領導者可用,出現數據丟失的可能。
在這兩種多線程模型中都存在線程池的使用。在半同步/半異步模型中,工作者線程可能為一個工作者線程池。消息隊列的線程同步的工作已經由ACE框架自動完成,是不是工作者線程越多越好呢? 答案是否定的。 多線程可以提高客戶的響應速度。比如同時有A,B兩個客戶端先后發起兩個請求,A請求完成的時間較長,B請求則可以很快完成,如果只有一個工作線程,那么B需要等待A請求完成以后才能收到自己的響應,對于A來說,它本來就不期待自己的請求很快被完成,實際的執行情況會是,A在期待的時間內收到響應,B則使用了A的時間才收到自己的響應,B的客戶滿意度就會很差。 如果使用多線程,A會延遲一點點收到自己的響應,而B也可以在合理的時間內收到自己的響應。 但是由于多線程有自己的開銷,就整個系統來說,單工作線程執行A和B的總時間回比多工作線程執行AB任務的總時間要短。
對于領導者/跟隨者模型中,必然存在一個對等的線程池,線程池的數目取決于系統能夠承受的數目,單就對于模型本身來說,線程池的線程數目越大,能夠承受的網絡蜂擁的極限值也越大。 但是如果執行每個請求的時間都很短,則系統中存在大量永遠也用不到的線程,浪費了系統的資源。
如果使用多處理器的系統,應用程序必然能夠從多線程(工作線程和跟隨者線程)結構中收益