首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Muduo 網絡編程入門:核心概念與 Echo 服務器實戰

     編輯:關於C++

系列規劃

本系列將涵蓋:UNP 簡單協議、Boost.Asio/Netty/Twisted 示例移植、Roundtrip/Pingpong 壓測、Multiplexer、文件傳輸、Pub/Sub Hub、SOCKS4a 代理、短網址 HTTP 服務、Sudoku 多線程演進等。示例代碼已收錄於 muduo/examples(下載:muduo-0.1.5-alpha.tar.gz)。

TCP 網絡編程的三個半核心事件

  1. 連接建立:Server accept、Client connect 成功。
  2. 連接斷開:主動 close/shutdown、被動 read 返回 0。
  3. 消息到達:FD 可讀——最關鍵,決定編程風格(阻塞/非阻塞、分包、應用層緩衝)。
  4. 消息發送完畢(半個):數據寫入 OS 發送緩衝,非對端已收到。低流量可忽略。

非阻塞編程的關鍵難點

  • 主動關閉時如何確保緩衝區數據發送完畢?
  • 連接被拒如何帶退避重試?
  • Edge-trigger vs Level-trigger?何時關注 EPOLLOUT?如何避免 busy-loop 或漏讀?
  • 為何非阻塞必須用應用層緩衝?(分包、單字節到達、Lighttpd 歷史漏洞)
  • 緩衝區設計權衡:大緩衝減少 syscall vs 10k 連接的內存佔用。Muduo 用 readv + 棧上空間巧妙解決。
  • 發送緩衝堆積導致內存暴漲如何流控?
  • 定時器如何與網絡 IO 共用線程避免鎖?

所有答案均在 Muduo 源碼中。

Muduo 設計哲學

減少「偶發複雜性」(Accidental Complexity),讓程序員專注業務邏輯。特點:

  • 僅支援 Linux 2.6+ 非阻塞 TCP。
  • 無需繼承基類、覆寫虛函數,僅註冊回調處理三個半事件。

Echo 服務器完整實現(幾十行)

// echo.h
class EchoServer {
public:
    EchoServer(EventLoop* loop, const InetAddress& listenAddr);
    void start();
private:
    void onConnection(const TcpConnectionPtr& conn);
    void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time);
    EventLoop* loop_;
    TcpServer server_;
};

// echo.cc
EchoServer::EchoServer(EventLoop* loop, const InetAddress& listenAddr)
: loop_(loop), server_(loop, listenAddr, "EchoServer") {
    server_.setConnectionCallback(boost::bind(&EchoServer::onConnection, this, _1));
    server_.setMessageCallback(boost::bind(&EchoServer::onMessage, this, _1, _2, _3));
}
void EchoServer::start() { server_.start(); }

void EchoServer::onConnection(const TcpConnectionPtr& conn) {
    LOG_INFO << conn->peerAddress().toHostPort() << " -> "
             << conn->localAddress().toHostPort() << " is "
             << (conn->connected() ? "UP" : "DOWN");
}
void EchoServer::onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp time) {
    string msg(buf->retrieveAsString());
    LOG_INFO << conn->name() << " echo " << msg.size() << " bytes at " << time.toString();
    conn->send(msg);
}

// main.cc
int main() {
    LOG_INFO << "pid = " << getpid();
    EventLoop loop;
    InetAddress listenAddr(2007);
    EchoServer server(&loop, listenAddr);
    server.start();
    loop.loop();
}

完整代碼見 muduo/examples/simple/echo。下一篇將詳細分析五個簡單 TCP 協議實現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved