• <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

            低調(diào)做技術(shù)__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

            剖析Etwork網(wǎng)絡(luò)庫

            Author : Kevin Lynx

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

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

            先看看下這個庫的結(jié)構(gòu):

            classgraph

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

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

            在功能實現(xiàn)上,我以TCP服務(wù)器為例,CreateEtwork根據(jù)傳來的參數(shù)建立服務(wù)器,在SocketManager::open中
            是很常規(guī)的socket, bind, listen。當(dāng)建立了服務(wù)器之后,需要在程序主循環(huán)里不斷地輪詢狀態(tài),這里主要
            調(diào)用poll函數(shù)完成。

            poll函數(shù)主體就是調(diào)用select。當(dāng)select成功返回活動的套接字?jǐn)?shù)量后,Etwork依次輪詢讀、寫、錯誤fdset,
            將保存的所有網(wǎng)絡(luò)連接(就是那些ISocket對象)對應(yīng)的套接字與fdset中當(dāng)前的套接字做比較。大致邏輯為:

            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 )
             


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

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

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

             

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

             

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

             

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

             

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

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

            Etwork中還有一個比較有趣的東西:marshaller。這個東西主要就是提供將C++中各種數(shù)據(jù)類型的變量進行字
            節(jié)編碼,也就是將int long struct之類的東西轉(zhuǎn)換為unsigned char,從而方便直接往網(wǎng)絡(luò)上發(fā)送。

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

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

            其他東西就沒什么好說的了,縱觀一下,Etwork實現(xiàn)得還是比較典型的,可以作為開發(fā)網(wǎng)絡(luò)庫的一個簡單例子。

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

            評論

            # re: 剖析Etwork網(wǎng)絡(luò)庫 2008-05-21 21:52 空明流轉(zhuǎn)

            做面向?qū)ο蟠蟮志褪莾蓚€極端,一個是回歸過程化的抽象,一個就是純面向?qū)ο蟆?br>
            不過感覺這個傾向是跟你長期從事的領(lǐng)域有關(guān)。  回復(fù)  更多評論   

            # re: 剖析Etwork網(wǎng)絡(luò)庫 2008-05-21 23:04 eXile

            我也是越來越不喜歡C++了,目前比較傾向于純C或Python。
            對于純C的網(wǎng)絡(luò)庫,可以試試 libevent 或 libev, 應(yīng)該算是比較好的庫了。  回復(fù)  更多評論   

            # re: 剖析Etwork網(wǎng)絡(luò)庫 2008-05-22 10:42 關(guān)中刀客

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

            # re: 剖析Etwork網(wǎng)絡(luò)庫 2008-05-22 17:56 bugs_killer

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

            自我感覺很好啊.  回復(fù)  更多評論   

            # re: 剖析Etwork網(wǎng)絡(luò)庫 2009-09-29 10:47 libev

            libev是網(wǎng)絡(luò)庫?@eXile
              回復(fù)  更多評論   

            一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 精品久久国产一区二区三区香蕉 | 国产精品日韩欧美久久综合| 亚洲一本综合久久| 2021久久精品免费观看| 亚洲午夜久久久久久久久久| 99久久这里只有精品| 国产精品无码久久四虎| 伊人久久无码中文字幕| 久久香蕉综合色一综合色88| 亚洲国产香蕉人人爽成AV片久久| 麻豆成人久久精品二区三区免费| 国产精品女同一区二区久久| 久久精品中文闷骚内射| 日本久久中文字幕| 日韩亚洲欧美久久久www综合网| 波多野结衣久久一区二区| 久久国产一区二区| 亚洲色婷婷综合久久| 蜜桃麻豆www久久国产精品| 久久er国产精品免费观看2| 久久人妻AV中文字幕| 久久久久久久亚洲精品| 亚洲精品高清久久| 国产一级做a爰片久久毛片| 无码人妻久久久一区二区三区 | 久久人人妻人人爽人人爽| 久久人人爽人人澡人人高潮AV| 99久久久精品| 国产成人无码久久久精品一| 亚洲中文字幕无码久久2020 | 日韩精品久久无码人妻中文字幕| 色偷偷91久久综合噜噜噜噜| 国产精品99久久久久久www| 青青青青久久精品国产 | 久久久久免费视频| 国产精品美女久久久久AV福利| 久久综合久久久| 久久99精品国产麻豆宅宅| 国产国产成人精品久久| 国产三级久久久精品麻豆三级|