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

作為第一層封裝,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;
維護一個在線用戶容器,提供添加、刪除、查找、遍歷等用戶管理功能,為上層業務邏輯屏蔽底層數據結構細節。
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;
}
負責服務端套接字的創建、綁定、監聽、非阻塞設置等初始化工作,對外提供監聽套接字描述符。
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 等。
服務端核心類,基於 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 | EPOLLETrecv 讀取數據 → 回顯發送 → 轉發至測試用 DB 連接epoll_ctl DEL → 關閉套接字構造函數中還包含測試代碼:主動連接一個固定 IP/端口的 DB 服務,用於後續數據轉發測試。
封裝 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