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)以后的部分,我一会儿再写。