(本文針對的是windows,linux下基於c++語言的網絡編程) linux
我從事的是企業級的軟件開發,縱觀當今的企業級軟件,單機模型已經愈來愈少,更多的是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的實現。
今天,對於網絡編程先整體而且歸納的介紹下吧,其實還有不少問題沒有涉及,我本人對網絡編程十分的感興趣,如今也在從事這方面的工做,因此之後有機會但願和你們一塊兒分享一些更細緻全面的知識,鑑於本人水平有限,但願你們能對文章中出現的錯誤給予批評指正,咱們一塊兒進步......