boost用asio设计TCP服务器的关键技术

来源:互联网 发布:js 乱码 编辑:程序博客网 时间:2024/06/08 00:01

    boost的asio可以设计TCP服务器,作为通用的服务器设计,测试客户端不限于boost写的client,用多个telnet可以完成并发的测试。

关键技术:

(1)管理多连接的类的设计;

(2)单连接的send和recv的处理;

(3)单连接的心跳保链的处理;

(4)io_service的并发线程的设计;

(5)针对多并发,串行化处理的strand类的使用。

针对(1)的类的设计,其设计的生命周期与服务器的生命周期一致,负责处理连接的建立,管理和销毁,取名为channel,每个tcp的连接,我取名叫session,channel类结构如下:

#pragma once  #include "session.h"//#include "card.h"//#define  CARD_NUM 8//typedef boost::shared_ptr<channel> channel_ptr;class channel{public:    channel(boost::asio::io_service &io_service, boost::asio::ip::tcp::endpoint &endpoint);    void handle_accept(session_ptr new_session, const boost::system::error_code& error);    void run();    void lastSessionSend(char* cmd);    void allSessionsSend(char* cmd);    void map_remove(int sessionId);    void oneSessionSend(char* cmd, int sessionId);private:    boost::asio::io_service &io_service_;    boost::asio::ip::tcp::acceptor acceptor_;    session_ptr last_session;    std::map<int,session_ptr> sessions;    //card cards[CARD_NUM];    boost::asio::strand strand_;    void _lastSessionSend(char* cmd);    void _allSessionsSend(char* cmd);    void _map_remove(int sessionId);    void _oneSessionSend(char* cmd, int sessionId);private:    channel(const channel& other);    const channel operator=( const channel& rhs);public:    typedef boost::system::error_code error_code;};  
boost::asio::ip::tcp::acceptor与handle_accept,负责接受tcp连接,handle_accept中建立连接的类session,

void channel::handle_accept(session_ptr new_session, const boost::system::error_code& error) {  if (error) {  return;  }  new_session->start();sessions[new_session->getSessionId()] =new_session;new_session->start_send("welcome to me!");last_session =new_session;session_ptr next_session(new session(io_service_,*this));  acceptor_.async_accept(next_session->socket(),  strand_.wrap(boost::bind(&channel::handle_accept,  this,  next_session,  boost::asio::placeholders::error)));  }  

每一个new_session调用start的方法后,acceptor_都会继续的异步等待新的连接,async_accept。

sessions是管理各个session的map,stl的map对于key-value的查找还是比较给力。

run的方法是channel的启动的主方法,核心部分就是启动io_service

    void channel::run() {    //boost::thread t(boost::bind(&boost::asio::io_service::run,boost::ref(io_service_)));        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(io_service_)));    boost::this_thread::sleep(boost::posix_time::seconds(5));    }    }  

调试的时候,可以单线程启动,发布的时候,可以根据硬件设备进行多线程启动。这里线程的多少与并发数的多少没有直接关系。

(4)中提到的io_service的并发线程的设计的方法,在这里也已解决。io_service是根据可用的cpu来确定线程的数量,而不是根据实际的工作来分配线程,这样能更充分的使用cpu资源,更加有效。

有了acceptor,map和run的方法,就能构成连接管理类的核心部分,当然其他的代码的功能是数据发送,map的管理,防拷贝等,也一样有用。

(2)以后的部分,我一会儿再写。

全部源代码下载连接在这里