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

            陳碩的Blog

            Muduo 網(wǎng)絡(luò)編程示例之零:前言

            陳碩 (giantchen_AT_gmail)

            Blog.csdn.net/Solstice

            Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx

            我將會寫一系列文章,介紹用 muduo 網(wǎng)絡(luò)庫完成常見的 TCP 網(wǎng)絡(luò)編程任務(wù)。目前計劃如下:

            1. UNP 中的簡單協(xié)議,包括 echo、daytime、time、discard 等。 
            2. Boost.Asio 中的示例,包括 timer2~6、chat 等。
            3. Java Netty 中的示例,包括 discard、echo、uptime 等,其中的 discard 和 echo 帶流量統(tǒng)計功能。
            4. Python twisted 中的示例,包括 finger01~07
            5. 云風(fēng)的串并轉(zhuǎn)換連接服務(wù)器 multiplexer,包括單線程和多線程兩個版本。
            6. 用于測試兩臺機器的往返延遲的 roundtrip
            7. 用于測試兩臺機器的帶寬的 pingpong
            8. 文件傳輸
            9. 一個基于 TCP 的應(yīng)用層廣播 hub
            10. socks4a 代理服務(wù)器,包括簡單的 TCP 中繼(relay)。
            11. 一個 Sudoku 服務(wù)器的演變,從單線程到多線程,從阻塞到 event-based。
            12. 一個提供短址服務(wù)的 httpd 服務(wù)器

            其中前面 7 個已經(jīng)放到了 muduo 代碼的 examples 目錄中,下載地址是: http://muduo.googlecode.com/files/muduo-0.1.5-alpha.tar.gz 

            這些例子都比較簡單,邏輯不復(fù)雜,代碼也很短,適合摘取關(guān)鍵部分放到博客上。其中一些有一定的代表性與針對性,比如“如何傳輸完整的文件”估計是網(wǎng)絡(luò)編程的初學(xué)者經(jīng)常遇到的問題。請注意,muduo 是設(shè)計來開發(fā)內(nèi)網(wǎng)的網(wǎng)絡(luò)程序,它沒有做任何安全方面的加強措施,如果用在公網(wǎng)上可能會受到攻擊,在后面的例子中我會談到這一點。

            本系列文章適用于 Linux 2.6.x (x > 25),主要測試發(fā)行版為 Ubuntu 10.04 LTSDebian 6.0 Squeeze,64-bit x86 硬件。

            TCP 網(wǎng)絡(luò)編程本質(zhì)論

            我認(rèn)為,TCP 網(wǎng)絡(luò)編程最本質(zhì)的是處理三個半事件:

            1. 連接的建立,包括服務(wù)端接受 (accept) 新連接和客戶端成功發(fā)起 (connect) 連接。
            2. 連接的斷開,包括主動斷開 (close 或 shutdown) 和被動斷開 (read 返回 0)。
            3. 消息到達,文件描述符可讀。這是最為重要的一個事件,對它的處理方式?jīng)Q定了網(wǎng)絡(luò)編程的風(fēng)格(阻塞還是非阻塞,如何處理分包,應(yīng)用層的緩沖如何設(shè)計等等)。
            4. 消息發(fā)送完畢,這算半個。對于低流量的服務(wù),可以不必關(guān)心這個事件;另外,這里“發(fā)送完畢”是指將數(shù)據(jù)寫入操作系統(tǒng)的緩沖區(qū),將由 TCP 協(xié)議棧負責(zé)數(shù)據(jù)的發(fā)送與重傳,不代表對方已經(jīng)收到數(shù)據(jù)。

            這其中有很多難點,也有很多細節(jié)需要注意,比方說:

            1. 如果要主動關(guān)閉連接,如何保證對方已經(jīng)收到全部數(shù)據(jù)?如果應(yīng)用層有緩沖(這在非阻塞網(wǎng)絡(luò)編程中是必須的,見下文),那么如何保證先發(fā)送完緩沖區(qū)中的數(shù)據(jù),然后再斷開連接。直接調(diào)用 close(2) 恐怕是不行的。
            2. 如果主動發(fā)起連接,但是對方主動拒絕,如何定期 (帶 back-off) 重試?
            3. 非阻塞網(wǎng)絡(luò)編程該用邊沿觸發(fā)(edge trigger)還是電平觸發(fā)(level trigger)?(這兩個中文術(shù)語有其他譯法,我選擇了一個電子工程師熟悉的說法。)如果是電平觸發(fā),那么什么時候關(guān)注 EPOLLOUT 事件?會不會造成 busy-loop?如果是邊沿觸發(fā),如何防止漏讀造成的饑餓?epoll 一定比 poll 快嗎?
            4. 在非阻塞網(wǎng)絡(luò)編程中,為什么要使用應(yīng)用層緩沖區(qū)?假如一次讀到的數(shù)據(jù)不夠一個完整的數(shù)據(jù)包,那么這些已經(jīng)讀到的數(shù)據(jù)是不是應(yīng)該先暫存在某個地方,等剩余的數(shù)據(jù)收到之后再一并處理?見 lighttpd 關(guān)于 \r\n\r\n 分包的 bug。假如數(shù)據(jù)是一個字節(jié)一個字節(jié)地到達,間隔 10ms,每個字節(jié)觸發(fā)一次文件描述符可讀 (readable) 事件,程序是否還能正常工作?lighttpd 在這個問題上出過安全漏洞
            5. 在非阻塞網(wǎng)絡(luò)編程中,如何設(shè)計并使用緩沖區(qū)?一方面我們希望減少系統(tǒng)調(diào)用,一次讀的數(shù)據(jù)越多越劃算,那么似乎應(yīng)該準(zhǔn)備一個大的緩沖區(qū)。另一方面,我們系統(tǒng)減少內(nèi)存占用。如果有 10k 個連接,每個連接一建立就分配 64k 的讀緩沖的話,將占用 640M 內(nèi)存,而大多數(shù)時候這些緩沖區(qū)的使用率很低。muduo 用 readv 結(jié)合棧上空間巧妙地解決了這個問題。
            6. 如果使用發(fā)送緩沖區(qū),萬一接收方處理緩慢,數(shù)據(jù)會不會一直堆積在發(fā)送方,造成內(nèi)存暴漲?如何做應(yīng)用層的流量控制?
            7. 如何設(shè)計并實現(xiàn)定時器?并使之與網(wǎng)絡(luò) IO 共用一個線程,以避免鎖。

            這些問題在 muduo 的代碼中可以找到答案。

            Muduo 簡介

            我編寫 Muduo 網(wǎng)絡(luò)庫的目的之一就是簡化日常的 TCP 網(wǎng)絡(luò)編程,讓程序員能把精力集中在業(yè)務(wù)邏輯的實現(xiàn)上,而不要天天和 Sockets API 較勁。借用 Brooks 的話說,我希望 Muduo 能減少網(wǎng)絡(luò)編程中的偶發(fā)復(fù)雜性 (accidental complexity)。

            Muduo 只支持 Linux 2.6.x 下的并發(fā)非阻塞 TCP 網(wǎng)絡(luò)編程,它的安裝方法見陳碩的 blog 文章

            Muduo 的使用非常簡單,不需要從指定的類派生,也不用覆寫虛函數(shù),只需要注冊幾個回調(diào)函數(shù)去處理前面提到的三個半事件就行了。

            以經(jīng)典的 echo 回顯服務(wù)為例:

            1. 定義 EchoServer class,不需要派生自任何基類:

             

             1 #ifndef MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H 
             2 #define MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
             3 
             4 #include <muduo/net/TcpServer.h>
             5 
             6 // RFC 862 
             7 class EchoServer 
             8 
             9 public
            10   EchoServer(muduo::net::EventLoop* loop, 
            11              const muduo::net::InetAddress& listenAddr);
            12 
            13   void start();
            14 
            15 private
            16   void onConnection(const muduo::net::TcpConnectionPtr& conn);
            17 
            18   void onMessage(const muduo::net::TcpConnectionPtr& conn, 
            19                  muduo::net::Buffer* buf, 
            20                  muduo::Timestamp time);
            21 
            22   muduo::net::EventLoop* loop_; 
            23   muduo::net::TcpServer server_; 
            24 };
            25 
            26 #endif  // MUDUO_EXAMPLES_SIMPLE_ECHO_ECHO_H
            27 

             

            在構(gòu)造函數(shù)里注冊回調(diào)函數(shù):

             

             1 EchoServer::EchoServer(EventLoop* loop, 
             2                        const InetAddress& listenAddr) 
             3   : loop_(loop), 
             4     server_(loop, listenAddr, "EchoServer"
             5 
             6   server_.setConnectionCallback( 
             7       boost::bind(&EchoServer::onConnection, this, _1)); 
             8   server_.setMessageCallback( 
             9       boost::bind(&EchoServer::onMessage, this, _1, _2, _3)); 
            10 }
            11 
            12 void EchoServer::start() 
            13 
            14   server_.start(); 
            15 
            16 
            17 

             

            2. 實現(xiàn) EchoServer::onConnection() 和 EchoServer::onMessage():

             

             1 void EchoServer::onConnection(const TcpConnectionPtr& conn) 
             2 
             3   LOG_INFO << "EchoServer - " << conn->peerAddress().toHostPort() << " -> " 
             4     << conn->localAddress().toHostPort() << " is " 
             5     << (conn->connected() ? "UP" : "DOWN"); 
             6 }
             7 
             8 void EchoServer::onMessage(const TcpConnectionPtr& conn, 
             9                            Buffer* buf, 
            10                            Timestamp time) 
            11 
            12   string msg(buf->retrieveAsString()); 
            13   LOG_INFO << conn->name() << " echo " << msg.size() << " bytes at " << time.toString(); 
            14   conn->send(msg); 
            15 }
            16 

             

            3. 在 main() 里用 EventLoop 讓整個程序跑起來:

             

             1 #include "echo.h"
             2 
             3 #include <muduo/base/Logging.h> 
             4 #include <muduo/net/EventLoop.h>
             5 
             6 using namespace muduo; 
             7 using namespace muduo::net;
             8 
             9 int main() 
            10 
            11   LOG_INFO << "pid = " << getpid(); 
            12   EventLoop loop; 
            13   InetAddress listenAddr(2007); 
            14   EchoServer server(&loop, listenAddr); 
            15   server.start(); 
            16   loop.loop(); 
            17 }
            18 

             

            完整的代碼見 muduo/examples/simple/echo。
            這個幾十行的小程序?qū)崿F(xiàn)了一個并發(fā)的 echo 服務(wù)程序,可以同時處理多個連接。
            對這個程序的詳細分析見下一篇博客《Muduo 網(wǎng)絡(luò)編程示例之一:五個簡單 TCP 協(xié)議》

            (待續(xù))

            posted on 2011-02-02 01:07 陳碩 閱讀(9379) 評論(0)  編輯 收藏 引用 所屬分類: muduo

            <2011年2月>
            303112345
            6789101112
            13141516171819
            20212223242526
            272812345
            6789101112

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            隨筆分類

            隨筆檔案

            相冊

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国产精品久久久久影视不卡| 久久精品人妻一区二区三区| 一本色道久久HEZYO无码| 精品久久久中文字幕人妻| 夜夜亚洲天天久久| 久久人妻AV中文字幕| 国产精品免费久久久久电影网| 久久久久人妻一区二区三区 | 国产精品久久久天天影视香蕉 | 99热成人精品热久久669| 久久久国产精华液| 99久久免费国产精品热| 久久久久人妻一区二区三区 | AV无码久久久久不卡网站下载| 久久久久国产一区二区| 久久综合丁香激情久久| 无码人妻久久一区二区三区| 久久夜色精品国产www| 四虎国产永久免费久久| 久久综合狠狠综合久久| 2019久久久高清456| 伊人久久精品影院| 色综合久久天天综线观看| 超级碰久久免费公开视频| 久久久久久久99精品免费观看| 一本色道久久综合亚洲精品| 欧美黑人激情性久久| 青春久久| 欧美日韩精品久久免费| 中文字幕无码久久精品青草| 久久无码人妻精品一区二区三区| A级毛片无码久久精品免费| 久久精品免费观看| 26uuu久久五月天| 久久播电影网| 婷婷久久精品国产| 老男人久久青草av高清| 国产精品美女久久福利网站| 久久天天躁夜夜躁狠狠| 五月丁香综合激情六月久久 | 无码任你躁久久久久久|