本文針對的是windows,linux下基於c++語言的網絡編程)
我從事的是企業級的軟件開發,縱觀當今的企業級軟件,單機模型已經越來越少,更多的是C/S模型,目前client和server之間通信是通過socket技術來實現的。
上面提到了socket技術,自然要學習TCP/IP協議,對於TCP/IP的理論,學習Richard的《TCP/IP詳解 卷1:協議》我認為是不二的選擇,這本書涵蓋內容很多,如果對於只是實現C/S通信的網絡庫而言,僅需要了解其中介紹UDP和TCP的章節就好,扎實的理論基礎會為你以後遇到網絡傳輸中出現的問題給予很好的解釋,也便於你解決這些問題。理論聯系實現,還是Richard的《UNIX網絡編程 卷1:套接口API》俗稱UNP1),這本書我一直在看,但是還沒看完,我認為這是網絡編程的聖經,你掌握了這本書,基本也就掌握了網絡編程,甚至細枝末節也能覆蓋到。
以下只涉及TCP協議)
緊接著學習轉為實踐,想想網絡通信的場景:一個server要對應成千上萬,甚至十萬..個客戶,這樣必須要考慮到server的處理能力。
最簡單的模型就是你用
一個進程來處理所有的客戶端連接,my god!你想想,在處理過程中如果有上百個連接同時請求服務,我們采用這種模式,首先下一個連接要等著上一個連接處理完同步),這個在處理的連接還很有可能阻塞在數據操作I/O)上,這樣處理連接的效率之差及客戶端的響應之慢我想幾乎沒有人能忍受吧。
好,為了提高效率,我們改進一下,
對每一個客戶連接產生一個線程windows)或進程linux)來處理,拋開線程或進程的上下文切換損耗不談,也不談SMP,就單單看產生成千上百個線程和進程的可行性,對不起,咱操作系統可是有線程或進程資源上限的。
為了解決線程頻繁切換造成的資源損耗和資源數限制問題,
我們再改進一下,采用一個線程池來處理部分連接,其他連接排隊等候,畢竟咱cpu不多,同時也就能處理那麼幾個連接,響應效率和處理效率依然提不上去。
想一個問題,其實我們的網絡耗時一般都是在數據操作上I/O),為了增加客戶端的響應,
我們可以把一次網絡接入分為處理連接的線程和進行邏輯處理的線程,這樣就可以極大地提高客戶端的響應,但是記住一定要在邏輯處理線程中維護住這個連接的會話。這樣仿佛還不錯,no,no,其實也不好,你並不知道什麼時候有數據到來需要處理,你必須要輪詢來確定可不可以進行數據操作....,效率還是不好啊。
好了,咱不自己獨創技術了,
選用經典的Reactor和Proactor並發編程模式,他們都是基於事件驅動的,咱呢就是把網絡中需要處理的事件注冊到事件管理器中去比如網絡行為事件,IO操作事件.....),然後等事件狀態就緒了,他就用回調的方式通知咱去處理,怎麼樣,這樣至少CPU不會閒著了,只用一個線程就可以處理幾乎所有的事件了。但是Reactor和Proactor還是有很大區別的,Reactor對於I/O這一步是需要自己處理的,但是Proactor對於I/O這一步是由操作系統完成的,然後把完成事件通知你,然後你就可以進行下一步操作了比如從緩沖區buf裡讀數據),比自己操作I/O這種方式快多了吧。目前,我在windows下寫網絡庫采用的是Proactor模式:用windows自己提供的完成端口模型
IOCP)實現,在linux下,由於linux沒有很好的異步I/O機制,只好采用Reactor方式了:使用的是linux特有的
epoll。談一些我自己的看法:從我的理解上,對於大部分網絡庫而言,很多都是I/O密集型的,這樣仿佛采用Proactor模式更有優勢,但是linux下沒有和windows下IOCP類似的機制,但是可以采用epoll加任務隊列的方式實現一套,但是仿佛很復雜,我想自己實現就算了吧。好在“山窮水復疑無路,柳暗花明又一村”,boost asio 已經為我們封轉好了windows和linux下的Proactor實現,windows采用的是完成端口,linux下采用的是epoll加任務隊列的方式實現。下一步我准備把目前linux下采用epoll方式實現的Reactor網絡庫改為boost asio的實現。
今天,對於網絡編程先總體並且概括的介紹下吧,其實還有很多問題沒有涉及,我本人對網絡編程十分的感興趣,現在也在從事這方面的工作,所以以後有機會希望和大家一起分享一些更細致全面的知識,鑒於本人水平有限,希望大家能對文章中出現的錯誤給予批評指正,我們一起進步......
本文出自 “永遠的朋友” 博客,請務必保留此出處http://yaocoder.blog.51cto.com/2668309/870553