本框架基於 Boost.Asio 非同步網路程式庫,模擬大量客戶端連線進行伺服器壓力測試。採用 Proactor 模式,單執行緒即可管理上萬連線,支援多執行緒擴展充分利用多核 CPU。
每個客戶端連線對應一個 CSession 物件,繼承 enable_shared_from_this 確保非同步操作期間物件存活:
class CSession : public boost::enable_shared_from_this{ public: CSession(const string& IP, unsigned short port, int heartbeat_min, boost::asio::io_service& ios); ~CSession(); void start(); // 發起非同步連線 void stop(); // 關閉連線與定時器 void login(); // 發送登入封包 void heartbeat(); // 發送心跳封包 void start_send(); // 從任務佇列取出封包發送 private: // 非同步操作回調 void connect_handler(const error_code& ec); void receive_handler(const error_code& ec, size_t bytes); void login_handler(const error_code& ec, size_t bytes); void heartbeat_handler(const error_code& ec); void send_handler(const error_code& ec); // 封包處理 size_t check_frame(const error_code& ec, size_t bytes); void parse_frame(const error_code& ec, size_t bytes); void start_receive(); // 成員變數 tcp::endpoint m_ep; tcp::socket m_sock; tcp::resolver m_resolver; array read_buffer, write_buffer; deadline_timer heartbeat_timer; int m_heartbeat_minutes; thread_safe_queue m_task_queue; };
void CSession::start() {
m_sock.async_connect(m_ep, bind(&CSession::connect_handler, shared_from_this(), placeholders::error));
}
void CSession::connect_handler(const error_code& ec) {
if (!ec) {
boost::this_thread::sleep(boost::posix_time::microseconds(500));
login(); // 連線成功後發送登入封包
} else {
boost::this_thread::sleep(boost::posix_time::seconds(60));
start(); // 連線失敗 60 秒後重試
}
}
void CSession::login() {
unsigned char buf[256];
UINT len = process_login(buf); // 組裝登入資料
m_sock.async_write_some(buffer(buf, len), bind(&CSession::login_handler, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
}
void CSession::heartbeat() {
unsigned char buf[256];
UINT len = process_heartbeat(buf);
m_sock.async_write_some(buffer(buf, len), bind(&CSession::heartbeat_handler, shared_from_this(), placeholders::error));
}
void CSession::heartbeat_handler(const error_code& ec) {
if (!ec) {
heartbeat_timer.expires_from_now(boost::posix_time::minutes(m_heartbeat_minutes));
heartbeat_timer.async_wait(bind(&CSession::heartbeat, shared_from_this()));
} else {
stop();
}
}
void CSession::start_receive() {
m_sock.async_receive(buffer(read_buffer), bind(&CSession::receive_handler, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
}
void CSession::receive_handler(const error_code& ec, size_t bytes) {
if (!ec) {
// 封包驗證與解析
async_read(m_sock, buffer(read_buffer), bind(&CSession::check_frame, shared_from_this(), placeholders::error, bytes), bind(&CSession::parse_frame, shared_from_this(), placeholders::error, bytes));
start_receive(); // 繼續接收下一個封包
} else {
stop();
}
}
class Client { public: shared_ptr session; };
vector clients(10000); // 1 萬個客戶端
io_service ios;
io_service::work work(ios); // 防止 io_service 提前結束
string IP = "192.168.1.1";
unsigned short port = 8000;
int heartbeat = 10; // 分鐘
// 建立並啟動所有客戶端
for (auto& c : clients) {
c.session = make_shared(IP, port, heartbeat, ios);
c.session->start();
}
// 多執行緒運行 io_service(充分利用多核)
int thread_count = max(1, (int)boost::thread::hardware_concurrency());
thread_group tg;
for (int i = 0; i < thread_count; i++) {
tg.create_thread(bind(&io_service::run, ref(ios)));
boost::this_thread::sleep(boost::posix_time::seconds(5)); // 錯峰啟動
}
// 發送測試任務
for (auto& c : clients) {
c.session->start_send(); // 將任務加入佇列觸發發送
}
shared_from_this 防止回調中物件被釋放async_read 搭配雙回調實作io_service::run 多線程並行處理