从零开始实现一个C++高性能服务器框架----TcpServer模块

简介

项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。

详细内容:日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。IO协程调度模块,基于ucontext_t实现非对称协程模型,以线程池的方式实现多线程,多协程协同调度,同时依赖epoll实现了事件监听机制。定时器模块,使用最小堆管理定时器,配合IO协程调度模块可以完成基于协程的定时任务调度。hook模块,将同步的系统调用封装成异步操作(accept, recv, send等),配合IO协程调度能够极大的提升服务器性能。Http模块,封装了sokcet常用方法,支持http协议解析,客户端实现连接池发送请求,服务器端实现servlet模式处理客户端请求,支持单Reator多线程,多Reator多线程模式的服务器。

TcpServer模块

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;
}
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值