• <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ò)編程示例之七:“串并轉(zhuǎn)換”連接服務(wù)器及其自動(dòng)化測試

            Muduo 網(wǎng)絡(luò)編程示例之七:連接服務(wù)器及其自動(dòng)化測試

            陳碩 (giantchen_AT_gmail)

            Blog.csdn.net/Solstice  t.sina.com.cn/giantchen

            這是《Muduo 網(wǎng)絡(luò)編程示例》系列的第七篇文章。

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

            本文介紹如何使用 test harness 來測試一個(gè)具有內(nèi)部邏輯的網(wǎng)絡(luò)服務(wù)程序。

            本文的代碼見 http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer

            下載地址:http://muduo.googlecode.com/files/muduo-0.2.0-alpha.tar.gz SHA1 checksum: 75a09a82f96b583004876e95105c679e64c95715

             

            云風(fēng)在他的博客中提到了網(wǎng)游連接服務(wù)器的功能需求(搜“練手項(xiàng)目”),我用 C++ 初步實(shí)現(xiàn)了這些需求,并為之編寫了配套的自動(dòng)化 test harness,作為 muduo 網(wǎng)絡(luò)庫的示例。

            注意:本文呈現(xiàn)的代碼僅僅實(shí)現(xiàn)了基本的功能需求,沒有考慮安全性,也沒有特別優(yōu)化性能,不適合用作真正的放在公網(wǎng)上運(yùn)行的網(wǎng)游連接服務(wù)器。

            功能需求

            這個(gè)連接服務(wù)器把多個(gè)客戶連接匯聚為一個(gè)內(nèi)部 TCP 連接,起到“數(shù)據(jù)串并轉(zhuǎn)換”的作用,讓 backend 的邏輯服務(wù)器專心處理業(yè)務(wù),而無需顧及多連接的并發(fā)性。以下是系統(tǒng)的框圖:

            multiplexer

            這個(gè)連接服務(wù)器的作用與數(shù)字電路中的數(shù)據(jù)選擇器 (multiplexer) 類似,所以我把它命名為 multiplexer。(其實(shí) IO-Multiplexing 也是取的這個(gè)意思,讓一個(gè) thread-of-control 能有選擇地處理多個(gè) IO 文件描述符。)

            mux

            (上圖取自 wikipedia,是 public domain 版權(quán))

            實(shí)現(xiàn)

            Multiplexer 的功能需求不復(fù)雜,無非是在 backend connection 和 client connections 之間倒騰數(shù)據(jù)。具體來說,主要是處理四種事件:

            由上可見,multiplexer 的功能與 proxy 頗為類似。multiplexer_simple.cc 是一個(gè)線程版的實(shí)現(xiàn),借助 muduo 的 io-multiplexing 特性,可以方便地處理多個(gè)并發(fā)連接。

            在實(shí)現(xiàn)的時(shí)候有兩點(diǎn)值得注意:

            • TcpConnection 的 id 如何存放?當(dāng)從 backend 收到數(shù)據(jù),如何根據(jù) id 找到對應(yīng)的 client connection?當(dāng)從 client connection 收到數(shù)據(jù),如何得知其 id ?

            第一個(gè)問題比較好解決,用 std::map〈int, TcpConnectionPtr〉 clientConns_; 保存從 id 到 client connection 的映射就行。

            第二個(gè)問題固然可以用類似的辦法解決,但是我想借此介紹一下 muduo::net::TcpConnection 的 context 功能。每個(gè) TcpConnection 都有一個(gè) boost::any 成員,可由客戶代碼自由支配(get/set),代碼如下。這個(gè) boost::any 是 TcpConnection 的 context,可以用于保存與 connection 綁定的任意數(shù)據(jù)(比方說 connection id、connection 的最后數(shù)據(jù)到達(dá)時(shí)間、connection 所代表的用戶的名字等等)。這樣客戶代碼不必繼承 TcpConnection 就能 attach 自己的狀態(tài),而且也用不著 TcpConnectionFactory 了(如果允許繼承,那么必然要向 TcpServer 注入此 factory)。

            class TcpConnection : public boost::enable_shared_from_this<TcpConnection>,
                                  boost::noncopyable
            {
             public:
            
              void setContext(const boost::any& context)
              { context_ = context; }
            
              boost::any& getContext()
              { return context_; }
            
              const boost::any& getContext() const
              { return context_; }
            
              // ...
            
             private:
              // ...
              boost::any context_;
            };
            
            typedef boost::shared_ptr<TcpConnection> TcpConnectionPtr;

            對于 Multiplexer,在 onClientConnection() 里調(diào)用 conn->setContext(id),把 id 存到 TcpConnection 對象中。onClientMessage() 從 TcpConnection 對象中取得 id,連同數(shù)據(jù)一起發(fā)送給 backend,完整實(shí)現(xiàn)如下:

              void onClientMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
              {
                if (!conn->getContext().empty())
                {
                  int id = boost::any_cast<int>(conn->getContext());
                  sendBackendBuffer(id, buf);
                }
                else
                {
                  buf->retrieveAll();
                }
              }
            • TcpConnection 的生命期如何管理?由于 Client Connection 是動(dòng)態(tài)創(chuàng)建并銷毀,其生與滅完全由客戶決定,如何保證 backend 想向它發(fā)送數(shù)據(jù)的時(shí)候,這個(gè) TcpConnection 對象還活著?解決思路是用 reference counting,當(dāng)然,不用自己寫,用 boost::shared_ptr 即可。TcpConnection 是 muduo 中唯一默認(rèn)采用 shared_ptr 來管理生命期的對象,蓋由其動(dòng)態(tài)生命期的本質(zhì)決定。更多內(nèi)容請參考陳碩《當(dāng)析構(gòu)函數(shù)遇到多線程──C++ 中線程安全的對象回調(diào)

            multiplexer 是二進(jìn)制協(xié)議,如何測試呢?

            自動(dòng)化測試

            Multiplexer 是 muduo 網(wǎng)絡(luò)編程示例中第一個(gè)具有 non-trivial 業(yè)務(wù)邏輯的網(wǎng)絡(luò)程序,根據(jù)陳碩《分布式程序的自動(dòng)化回歸測試》一文的思想,我為它編寫了 test harness。代碼見 http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer

            這個(gè) Test harness 采用 Java 編寫,用的是 Netty 庫。這個(gè) test harness 要扮演 clients 和 backend,也就是既要主動(dòng)發(fā)起連接,也要被動(dòng)接受連接。結(jié)構(gòu)如下:

            harness

            Test harness 會(huì)把各種 event 匯聚到一個(gè) blocking queue 里邊,方便編寫 test case。Test case 則操縱 test harness,發(fā)起連接、發(fā)送數(shù)據(jù)、檢查收到的數(shù)據(jù),例如以下是其中一個(gè) test case

            http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer/harness/src/com/chenshuo/muduo/example/multiplexer/testcase/TestOneClientSend.java

            這里的幾個(gè) test cases 都以用 java 直接寫的,如果有必要,也可以采用 Groovy 來編寫,這樣可以在不重啟 test harness 的情況下隨時(shí)修改添加 test cases。具體做法見陳碩《“過家家”版的移動(dòng)離線計(jì)費(fèi)系統(tǒng)實(shí)現(xiàn)》。

            將來的改進(jìn)

            有了這個(gè)自動(dòng)化的 test harness,我們可以比較方便且安全地修改(甚至重新設(shè)計(jì))multiplexer。例如
            • 增加“backend 發(fā)送指令斷開 client connection”的功能。有了自動(dòng)化測試,這個(gè)新功能可以被單獨(dú)測試(指開發(fā)者測試),而不需要真正的 backend 參與進(jìn)來。
            • 將 Multiplexer 改用多線程重寫。有了自動(dòng)化回歸測試,我們不用擔(dān)心破壞原有的功能,可以放心大膽地重寫。而且由于 test harness 是從外部測試,不是單元測試,重寫 multiplexer 的時(shí)候不用動(dòng) test cases,這樣保證了測試的穩(wěn)定性。另外,這個(gè) test harness 稍作改進(jìn)還可以進(jìn)行 stress testing,既可用于驗(yàn)證多線程 multiplexer 的正確性,亦可對比其相對單線程版的效率提升。

            posted on 2011-05-02 19:47 陳碩 閱讀(2484) 評論(0)  編輯 收藏 引用 所屬分類: muduo

            <2025年8月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            31123456

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            隨筆分類

            隨筆檔案

            相冊

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            一97日本道伊人久久综合影院| 久久久久人妻精品一区二区三区 | 性做久久久久久久久老女人| 亚洲欧美成人久久综合中文网| 亚洲国产另类久久久精品小说 | 伊人久久综合精品无码AV专区| 精品人妻久久久久久888| 久久这里有精品视频| 久久婷婷五月综合色奶水99啪 | 久久九九久精品国产免费直播| 久久天天躁狠狠躁夜夜avapp | 亚洲国产一成人久久精品| 国产精品gz久久久| 久久天天躁狠狠躁夜夜96流白浆 | 国产精品久久久久国产A级| 日本久久中文字幕| 精品久久久久久国产牛牛app| 亚洲国产另类久久久精品| 青青青青久久精品国产h久久精品五福影院1421 | 无码人妻久久一区二区三区蜜桃 | 久久久亚洲AV波多野结衣| 国内精品久久久久久麻豆| …久久精品99久久香蕉国产| 久久永久免费人妻精品下载| 久久午夜无码鲁丝片秋霞 | 久久99国产综合精品女同| 大香伊人久久精品一区二区| 欧美一级久久久久久久大片| 久久久久无码中| 人妻少妇精品久久| 亚洲午夜精品久久久久久浪潮| 精品国产91久久久久久久a| 久久精品国产99国产电影网| 成人久久久观看免费毛片| 69SEX久久精品国产麻豆| 久久香蕉综合色一综合色88| 精品久久国产一区二区三区香蕉| 国产伊人久久| 2021久久精品免费观看| 亚洲人成网亚洲欧洲无码久久| 亚洲av伊人久久综合密臀性色|