• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            loop_in_codes

            低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

            剖析Etwork網絡庫

            Author : Kevin Lynx

            從開始接觸網絡編程這個東西開始,我就不間斷地閱讀一些網絡庫(模塊)的源代碼,主要目的是為了獲取別
            人在這方面的經驗,編程這東西,還是要多實踐啊。

            基本上,Etwork是一個很小巧的網絡庫。Etwork基于select模型,采用我之前說的技巧,理論上可以處理很
            多連接(先不說效率)。

            先看看下這個庫的結構:

            classgraph

            如同很多網絡庫一樣,總會有一個類似于ISocketManager的類,用于管理所有網絡連接(當用戶服務器時)。
            而ISocket則用于代表一個網絡連接。在其他庫中,ISocketManager對應的可能就是Server,而ISocket對應
            的則是Session。

            在接口設計上,盡管Etwork寫了很多接口類(看看那些IClass),但是事實上它抽象得并不徹底。只是暴露給
            客戶端的代碼很簡潔,而庫本身依然臃腫。不知道為什么,現在我比較喜歡純C這種簡潔的東西,對于OO以及
            template,漸漸地有點心累。

            在功能實現上,我以TCP服務器為例,CreateEtwork根據傳來的參數建立服務器,在SocketManager::open中
            是很常規的socket, bind, listen。當建立了服務器之后,需要在程序主循環里不斷地輪詢狀態,這里主要
            調用poll函數完成。

            poll函數主體就是調用select。當select成功返回活動的套接字數量后,Etwork依次輪詢讀、寫、錯誤fdset,
            將保存的所有網絡連接(就是那些ISocket對象)對應的套接字與fdset中當前的套接字做比較。大致邏輯為:

            fd_count = select( 0, readset, writeset, exceptset, &timeout ); 

            for( each fd in readset )
                
            if( fd is listening fd ) 
                    accept 
            new connection
                
            else
                    
            for( each socket in all connections )
                        
            if( fd == socket )
                            can read data on 
            this socket 

            for( each fd in writeset )
             

            for( each fd in exceptset )
             


            沒什么特別讓人注意的地方(別覺得別人垃圾,耐心讀別人的代碼不是什么壞事)。每一次,當Etwork檢測到
            新的連接時,會創建新的ISocket對象,并關聯對應的套接字,然后保存此對象到一個列表中。當poll結束
            后,客戶端程序通常會調用accept函數(Etwork中提供的接口),該函數主要是將poll中保存的新的ISocket
            對象全部拷貝出去。

            在接收、發送網絡數據上,Etwork如同幾乎所有的網絡庫(模塊)一樣,采用了緩沖機制。這里所說的緩沖機
            制是,網絡模塊接收到網絡數據時,將數據保存起來,客戶端程序想獲取數據時,實際上就是從這個緩沖中
            直接取,而不是從網絡上獲取;同理,發送數據時,客戶端程序將數據提供給網絡模塊,網絡模塊將數據保
            存起來,網絡模塊會在另一個時候發送這個緩沖中的數據(對于異步IO的處理畢竟不一樣)。

            Etwork關于這個緩沖機制的相關代碼,主要集中在Buffer這個類。與Buffer相關的是一個Message機制。Buffer
            維護了一個Message的隊列(deque)。一個Message實際上是一個非常簡單的結構體:

             

            struct Message 
            {
                unsigned 
            short offset_;
                unsigned 
            short size_;
            }

             

            這其實是消息頭,在消息頭后全部是數據。在創建消息時(new_message),Etwork根據客戶端提供的數據創建
            足夠大的緩存保存:

             

            Message * m = (Message *)::operator new( size + sizeof( Message ) ); 

             

            這其實是一個很危險的做法,但是從Etwokr的源碼可以看出來,作者很喜歡玩弄這個技巧。與Buffer具體相
            關的接口包括:get_data, put_data, get_message, put_message。Buffer內部維護的數據都是以Message
            的形式組織。但是,對于外部而言,卻依然是raw data,也就是諸如char*之類的數據。幾個相關函數大致
            上的操作為:獲取指定尺寸的消息(可能包含多個消息),將一段數據加入Buffer并以消息的形式組織(可能會
            創建多個消息),將一個消息以raw data的形式輸出,將raw data以一個消息的形式加入到Buffer。

            一般情況下,Etwork的poll操作,會將套接字上的數據接收并put_data到緩沖中;發送數據時則get_data。
            客戶端要從緩沖中獲取數據時,就調用get_message;發送數據時就put_message。

            Etwork中還有一個比較有趣的東西:marshaller。這個東西主要就是提供將C++中各種數據類型的變量進行字
            節編碼,也就是將int long struct之類的東西轉換為unsigned char,從而方便直接往網絡上發送。

            基本上,Buffer和marshaller可以說是一個網絡庫(模塊)的必要部件,你可以在不同的網絡庫中看到類似的
            東西。

            Etwork在網絡事件的處理上,除了上面的輪詢外,還支持回調機制。這主要是通過INotify,以及給各個ISocket
            注冊Notify對象實現。沒什么難度,基本上就是observer模式的簡單實現。

            其他東西就沒什么好說的了,縱觀一下,Etwork實現得還是比較典型的,可以作為開發網絡庫的一個簡單例子。

            posted on 2008-05-21 21:06 Kevin Lynx 閱讀(7005) 評論(5)  編輯 收藏 引用 所屬分類: network

            評論

            # re: 剖析Etwork網絡庫 2008-05-21 21:52 空明流轉

            做面向對象大抵就是兩個極端,一個是回歸過程化的抽象,一個就是純面向對象。

            不過感覺這個傾向是跟你長期從事的領域有關。  回復  更多評論   

            # re: 剖析Etwork網絡庫 2008-05-21 23:04 eXile

            我也是越來越不喜歡C++了,目前比較傾向于純C或Python。
            對于純C的網絡庫,可以試試 libevent 或 libev, 應該算是比較好的庫了。  回復  更多評論   

            # re: 剖析Etwork網絡庫 2008-05-22 10:42 關中刀客

            很多時候底層還是自己寫比較的好~~~  回復  更多評論   

            # re: 剖析Etwork網絡庫 2008-05-22 17:56 bugs_killer

            ACE設計得就很好啊..我基于ACE裁剪過一個輕型的通信庫.
            http://code.google.com/p/netdkit/

            自我感覺很好啊.  回復  更多評論   

            # re: 剖析Etwork網絡庫 2009-09-29 10:47 libev

            libev是網絡庫?@eXile
              回復  更多評論   

            热re99久久精品国产99热| 久久天天躁狠狠躁夜夜av浪潮 | 狠狠色丁香久久婷婷综| 欧美亚洲另类久久综合| 国内精品免费久久影院| 久久天天婷婷五月俺也去| 久久AV高潮AV无码AV| 久久国产精品成人免费| 伊人久久无码精品中文字幕| 香蕉久久夜色精品升级完成| 国产精品成人99久久久久91gav| 国产一区二区久久久| 久久精品国产亚洲沈樵| 久久久久久久波多野结衣高潮 | 精品多毛少妇人妻AV免费久久| 亚洲伊人久久综合中文成人网| 9久久9久久精品| 中文字幕无码免费久久| 久久AⅤ人妻少妇嫩草影院| 麻豆一区二区99久久久久| 久久精品无码一区二区三区免费 | 久久国语露脸国产精品电影| 久久99精品久久久久久噜噜| 久久AV高清无码| 久久精品日日躁夜夜躁欧美| 久久人人爽人人精品视频| 色综合色天天久久婷婷基地 | 久久综合色之久久综合| 99久久亚洲综合精品网站| 精品国产乱码久久久久久1区2区| 久久午夜无码鲁丝片秋霞| 久久精品国产精品亜洲毛片| 99久久精品国产一区二区蜜芽| 久久香蕉国产线看观看99| 99久久成人国产精品免费| www.久久99| 国产午夜电影久久| 久久91这里精品国产2020| 久久99精品久久久久久齐齐 | 亚洲一区二区三区日本久久九| 久久66热人妻偷产精品9|