简介
项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。
详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。
TcpServer模块![](https://img-blog.csdnimg.cn/direct/54492d099b8f447b8f655265b460f040.png)
1. 主要功能
- 负责Tcp服务端的相关工作,包括监听,处理客户端响应,设置超时时间等
- 和三个IO协程调度器绑定,能够实现监听,处理客户端读写,处理业务逻辑的分离
- 充当监听池,负责所有监听socket的监听工作
2. 功能演示
- 这一部分的功能需要结合Http通信完成,具体可以参考后续文章从零开始实现一个C++高性能服务器框架----Http模块
3. 模块介绍
3.1 TcpServer
- 基类,包含了Tcp服务端的一些操作,包括监听,处理客户端响应,设置超时时间等
class TcpServer : public std::enable_shared_from_this<TcpServer>
, Noncopyable {
public:
typedef std::shared_ptr<TcpServer> ptr;
/**
* @brief 构造函数
* @param[in] worker socket客户端工作的协程调度器
* @param[in] io_woker socket客户端读写的协程调度器
* @param[in] accept_worker 服务器socket执行接收socket连接的协程调度器
*/
TcpServer(johnsonli::IOManager* worker = johnsonli::IOManager::GetThis()
,johnsonli::IOManager* io_woker = johnsonli::IOManager::GetThis()
,johnsonli::IOManager* accept_worker = johnsonli::IOManager::GetThis());
virtual ~TcpServer();
virtual bool bind(johnsonli::Address::ptr addr, bool ssl = false);
virtual bool bind(const std::vector<Address::ptr>& addrs
,std::vector<Address::ptr>& fails
,bool ssl = false);
virtual bool start();
virtual void stop();
// get set 方法
protected:
virtual void handleClient(Socket::ptr client); // 处理新连接的Socket类,读写,逻辑处理
virtual void startAccept(Socket::ptr sock); // 开始接受连接
private:
std::vector<Socket::ptr> m_socks; /// 监听Socket数组
IOManager* m_worker; /// 新连接的Socket工作的调度器
IOManager* m_ioWorker;
IOManager* m_acceptWorker; /// 服务器Socket接收连接的调度器
uint64_t m_recvTimeout; /// 接收超时时间(毫秒)
std::string m_name; /// 服务器名称
std::string m_type = "tcp"; /// 服务器类型
bool m_isStop; /// 服务是否停止
bool m_ssl = false;
};
- 当TcpServer完成
bind
后,就可以调用start()
方法,这里m_acceptWorker调度器会专门负责所有监听socket的监听工作
bool TcpServer::start()
{
if(!m_isStop)
{
return true;
}
m_isStop = false;
//每个listen socket都需要进行accept
for(auto& sock : m_socks)
{
//专门负责accept的协程调度器
m_acceptWorker->schedule(std::bind(&TcpServer::startAccept,
shared_from_this(), sock));
}
return true;
}
- 负责监听的函数
startAccept
。当accept监听到连接请求时(hook的accept),会为连接socket设置超时时长(未在规定时间内发送请求,就会断开这个连接),m_ioWorker调度器负责连接socket的读写。
void TcpServer::startAccept(Socket::ptr sock)
{
while(!m_isStop)
{
LOG_INFO(g_logger) << "startAccept";
Socket::ptr client = sock->accept();
//accept成功
if(client)
{
client->setRecvTimeout(m_recvTimeout);
//专门处理client socket的协程调度器
//LOG_INFO(g_logger) << "schedule handleClient";
m_ioWorker->schedule(std::bind(&TcpServer::handleClient, shared_from_this(), client));
}
else
{
LOG_ERROR(g_logger) << "accept errno=" << errno
<< " errstr=" << strerror(errno);
}
}
}
- 负责连接socket的读写
handleClient
。针对不同的子类,会有不同的处理逻辑
void TcpServer::handleClient(Socket::ptr client)
{
LOG_INFO(g_logger) << "handleClient: " << *client;
}