C++实现服务器压力测试框架

来源:互联网 发布:淘宝客佣金退款规则 编辑:程序博客网 时间:2024/06/05 20:18

C++实现服务器压力测试框架

flyfish 2015-3-9


模拟大量客户端对服务器进行压力测试框架

头文件
#pragma once#include <boost/asio.hpp> #include <boost/array.hpp> #include <boost/bind.hpp>#include <boost/asio/deadline_timer.hpp>#include <boost/enable_shared_from_this.hpp>class CSession: public boost::enable_shared_from_this<CSession>{public:CSession(const std::string IP, unsigned short port,int m_heartbeat_timer_minutes,boost::asio::io_service& io_service_);~CSession(void);private:boost::asio::ip::tcp::endpoint m_ep;boost::asio::ip::tcp::socket m_sock;boost::asio::ip::tcp::resolver m_resolver;boost::array<unsigned char, 4096> read_buffer;boost::array<unsigned char, 4096> write_buffer;boost::asio::deadline_timer heartbeat_timer;int m_heartbeat_timer_minutes;//心跳间隔 以分为单位void receive_handler(const boost::system::error_code &ec, std::size_t bytes_transferred);//接收数据处理结果void connect_handler(const boost::system::error_code &ec); //连接处理结果void heartbeat_handler(const boost::system::error_code &ec); //心跳处理结果void login_handler(const boost::system::error_code &ec,std::size_t bytes_transferred);//登录结果的处理void start_receive();//开始接收数据void send_handler(const boost::system::error_code &ec);std::size_t check_frame(const boost::system::error_code &ec, std::size_t bytes_transferred);//校验数据void parse_frame(const boost::system::error_code &ec, std::size_t bytes_transferred);//解析数据public:void start_send();//其他地方调用时 只需要把任务加到任务队列 执行 io_service_.post(boost::bind(&CSession::start_send, this));void start();//启动停止void stop();void login();//登录void heartbeat();//心跳task m_task_queue;//线程安全的任务队列};

实现文件

#include "Session.h"CSession::CSession(  const std::string IP,unsigned short port,int heartbeat_timer_minutes,boost::asio::io_service& io_service_): m_resolver(io_service_),m_sock(io_service_),heartbeat_timer(io_service_),m_nConnectState(0),m_ep(boost::asio::ip::address::from_string(IP),port),m_pObj(nullptr),m_heartbeat_timer_minutes(heartbeat_timer_minutes),m_nHeartbeatCount(0){read_buffer.fill(0);}void CSession::start(){m_sock.async_connect(m_ep,boost::bind(&CSession::connect_handler,shared_from_this(),boost::asio::placeholders::error));}CSession::~CSession(void){stop();}void CSession::stop(){heartbeat_timer.cancel();m_sock.close();}std::size_t CSession::check_frame(const boost::system::error_code &ec, std::size_t bytes_transferred){//bytes_transferred 已经接收的字节数//返回0 表示 验证通过//返回1 表示 需要继续验证}void CSession::parse_frame(const boost::system::error_code &ec, std::size_t bytes_transferred){if (!ec) { }}void CSession::start_receive(){m_sock.async_receive(boost::asio::buffer(read_buffer), boost::bind(&CSession::receive_handler,shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));}void CSession::receive_handler(const boost::system::error_code &ec, std::size_t bytes_transferred) { if (!ec) { //check_frame 验证接收的数据,当验证成功时,开始boost::asio::async_read(m_sock,boost::asio::buffer(read_buffer),boost::bind(&CSession::check_frame,shared_from_this(), boost::asio::placeholders::error,bytes_transferred),boost::bind(&CSession::parse_frame,shared_from_this(),boost::asio::placeholders::error,bytes_transferred));m_sock.async_receive(boost::asio::buffer(read_buffer), boost::bind(&CSession::receive_handler,shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));} else{stop();}} void CSession::heartbeat(){unsigned char c[256];UINT nLen = process_hartbeat(c);//生成心跳数据m_sock.async_write_some(boost::asio::buffer(c,nLen),boost::bind(&CSession::heartbeat_handler,shared_from_this(),boost::asio::placeholders::error));}void CSession::heartbeat_handler(const boost::system::error_code &ec){if (!ec){heartbeat_timer.expires_from_now(boost::posix_time::minutes(m_heartbeat_timer_minutes));heartbeat_timer.async_wait(boost::bind(&CSession::heartbeat,shared_from_this()));}else{stop();}}void CSession::login()//登录{//连接完成 发送登录帧//*******************************************************************************************unsigned char c[256];UINT nLen = process_login(c);//生成登录数据 例如 c中存储了用户名称和密码等m_sock.async_write_some(boost::asio::buffer(c,nLen),boost::bind(&CSession::login_handler,shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));}void CSession::login_handler(const boost::system::error_code &ec,std::size_t bytes_transferred){if (!ec) { start_receive();//启动接收heartbeat();}else{stop();}}void CSession::connect_handler(const boost::system::error_code &ec) { if (!ec) { boost::this_thread::sleep(boost::posix_time::microseconds(500));login();//连接成功之后开始登录}else{boost::this_thread::sleep(boost::posix_time::microseconds(60000));start();//连接失败 需要再次连接}} void CSession::start_send(){//从线程安全的任务队列中获取一个任务开始发送std::tuple<bool,task> ret=m_task_queue.get_nonblock();if (std::get<0>(ret)){unsigned char* c=std::get<1>(ret).data;int nLen=std::get<1>(ret).len;/**************************************************************************************************/m_sock.async_write_some(boost::asio::buffer(c,nLen),boost::bind(&CSession::send_handler,shared_from_this(),boost::asio::placeholders::error));}}void CSession::send_handler(const boost::system::error_code &ec){if (!ec) { start_send();//任务队列不为空时,开始发送下一个任务}}

在start中调用async_connect,当连接完成时,connect_handler就会被调用,通过 ec查看有没有连接成功, 
每当有一个或多个字节被接收并保存至缓冲区时,receive_handler() 函数就会被调用。
通过 ec查看有没有接收成功,  bytes_transferred 表示具体接收的字节数。

为了接受缓冲区 staying alive,所以使用了enable_shared_from_this
shared_from_this不能在构造函数中使用,所以连接函数放在start中




使用方式


class client{public:boost::shared_ptr<CSession> m_pSocket;//创建继承于enable_shared_from_this类的对象时必须使用智能指针};std::vector<client> client_queue;//存储生成的客户端实例boost::asio::io_service m_io_service;boost::asio::io_service::work m_work(m_io_service);//即使io任务完成,也不退出std::string IP="192.168.1.1";unsigned short port=8000;int heartbeat=10;for (int i=0;i<client_queue.size();i++){boost::shared_ptr<CSession>p (new CSession(IP,port,heartbeat,(m_io_service)));client_queue.at(i)->m_pSocket->start();}boost::thread t(boost::bind(&boost::asio::io_service::run,boost::ref(m_io_service)));


多线程调用run方式

int thread_count=(std::max)(static_cast<int>(boost::thread::hardware_concurrency()),1);//至少有一个线程运行boost::thread_group tg;for (int i=0;i<thread_count;i++){tg.create_thread(boost::bind(&boost::asio::io_service::run,boost::ref(m_io_service)));boost::this_thread::sleep(boost::posix_time::seconds(5));}

只要将任务加入到任务队列,执行 m_pSocket->start_send();


1 0
原创粉丝点击