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

仿 Muduo 設計的輕量級 C++ 網絡庫實現

     編輯:關於C++

整體架構

這是一個參考 Muduo 網絡庫設計的簡易 C++ 網絡庫初版,核心類包括 Server、Epoll、Socket、Accept、User 五大組件。代碼主要展示架構設計,I/O 處理尚不完善,部分功能待後續迭代完善。

網絡庫架構圖

1. Accept 類:連接接收器

作為第一層封裝,Accept 類專責處理客戶端連接請求,為上層提供已建立連接的套接字描述符。

class FDB_Accept {
public:
    FDB_Accept() = default;
    explicit FDB_Accept(int listen_fd);
    ~FDB_Accept();

    int getAccepted_fd() const;

private:
    int m_iAccepted_fd;
    struct sockaddr_in m_Client_addr;
    socklen_t m_cli_AddrLength = sizeof(m_Client_addr);
};
FDB_Accept::FDB_Accept(int listen_fd) {
    m_iAccepted_fd = accept(listen_fd,
                           (struct sockaddr*)&m_Client_addr,
                           &m_cli_AddrLength);
    if (m_iAccepted_fd == -1) {
        std::cerr << "accept ERROR!" << std::endl;
    }
}

int FDB_Accept::getAccepted_fd() const {
    return m_iAccepted_fd;
}

FDB_Accept::~FDB_Accept() = default;

2. User 類:在線用戶管理

維護一個在線用戶容器,提供添加、刪除、查找、遍歷等用戶管理功能,為上層業務邏輯屏蔽底層數據結構細節。

class FDB_Users {
public:
    FDB_Users() = default;
    ~FDB_Users() = default;

    void User_add(const FDB_Accept& user);
    bool User_del(int fd);
    bool User_find(int fd) const;
    bool User_show() const;
    FDB_Accept get_Accepter(int fd) const;

private:
    std::vector<FDB_Accept> m_vct_Acpt_User_data;
};
void FDB_Users::User_add(const FDB_Accept& user) {
    m_vct_Acpt_User_data.push_back(user);
}

bool FDB_Users::User_del(int fd) {
    for (auto it = m_vct_Acpt_User_data.begin();
         it != m_vct_Acpt_User_data.end(); ++it) {
        if (it->getAccepted_fd() == fd) {
            m_vct_Acpt_User_data.erase(it);
            return true;
        }
    }
    return false;
}

bool FDB_Users::User_find(int fd) const {
    for (const auto& user : m_vct_Acpt_User_data) {
        if (user.getAccepted_fd() == fd) return true;
    }
    return false;
}

bool FDB_Users::User_show() const {
    for (const auto& user : m_vct_Acpt_User_data) {
        std::cout << "On line user acpted_fd: "
                  << user.getAccepted_fd() << std::endl;
    }
    return true;
}

3. Socket 類:服務端套接字封裝

負責服務端套接字的創建、綁定、監聽、非阻塞設置等初始化工作,對外提供監聽套接字描述符。

class FDB_Socket {
public:
    explicit FDB_Socket(int sockfd) : m_iSockfd(sockfd) {}
    FDB_Socket(sa_family_t family, int listen_num);
    ~FDB_Socket();

    bool Socket_createSocket(sa_family_t family = AF_INET, int backlog = 100);
    bool Socket_bindAddress();
    bool Socket_listen(int backlog);
    bool Socket_setReusePort(bool on);
    bool Socket_setReuseAddr(bool on);
    bool Socket_setKeepAlive(bool on);
    bool Socket_TcpNoDelay(bool on);
    int  Socket_setNoBlocking();
    int  Socket_getfd() const { return m_iSockfd; }
    int  Socket_do_accept();
    bool Socket_shutdownWrite();
    bool test_accept();

private:
    int m_iSockfd;
    int m_iBacklog;
    struct sockaddr_in m_addr_inAddress;
    struct sockaddr_in m_addr_inCliaddr;
};

構造函數中鏈式調用創建、綁定、監聽、設置非阻塞,任何一步失敗即返回。關鍵設置包括 SO_REUSEPORT、SO_REUSEADDR、SO_KEEPALIVE、TCP_NODELAY 等。

4. Epoll 類:事件循環核心

服務端核心類,基於 epoll 實現 I/O 多路復用,主循環監聽讀寫事件並分發處理。

class FDB_Epoll {
public:
    explicit FDB_Epoll(int listen_fd);
    ~FDB_Epoll();

    bool Epoll_create_events();
    bool Epoll_add_initListen(int fd, bool enable_et);
    bool Epoll_add(int fd, bool enable_et, bool oneshot);
    bool Epoll_reset(int fd);
    bool Epoll_del(int fd);
    void Epoll_wait();  // 核心事件循環

private:
    int m_iEpoll_fd;
    const int m_ciMAX_NUM = 100;
    int m_iListen_fd;
    int m_iDBfd;  // 測試用數據庫連接
    epoll_event* m_epEvent_p;
    static FDB_Users user;  // 用戶管理單例
};

Epoll_wait() 為核心循環:調用 epoll_wait 獲取就緒事件,遍歷處理:

  • 監聽套接字可讀 → Accept 新連接 → 加入用戶管理 → 註冊 EPOLLIN | EPOLLET
  • 普通連接可讀 → recv 讀取數據 → 回顯發送 → 轉發至測試用 DB 連接
  • 連接關閉/錯誤 → 從用戶管理移除 → epoll_ctl DEL → 關閉套接字

構造函數中還包含測試代碼:主動連接一個固定 IP/端口的 DB 服務,用於後續數據轉發測試。

5. Server 類:多線程服務器封裝

封裝 Socket 和 Epoll,啟動多個工作線程,每個線程運行獨立的 Epoll 事件循環,利用 SO_REUSEPORT 實現多線程負載均衡。

class FDB_Server {
public:
    FDB_Server(int status, int max_conn, int thread_num);
    ~FDB_Server();
    bool server_start();
    int  get_server_fd() const;

private:
    int m_iServer_status;
    int m_iConnfd_num;
    int m_iSocketfd;
    int m_iServer_thread_num;
};

static void server_work(int listen_fd) {
    FDB_Epoll epo(listen_fd);
    epo.Epoll_wait();
}

bool FDB_Server::server_start() {
    FDB_Socket db_Server(AF_INET, 10);
    m_iSocketfd = db_Server.Socket_getfd();

    std::vector<std::thread> threads;
    threads.reserve(m_iServer_thread_num);
    for (int i = 0; i < m_iServer_thread_num; ++i) {
        threads.emplace_back(server_work, m_iSocketfd);
    }
    for (auto& t : threads) t.join();
    return true;
}

完整代碼倉庫: GitHub - my_netlib

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