当前位置: 首页 > news >正文

llfc项目TCP服务器笔记

ChatServer

一个TCP服务器必然会有连接的接收,维持,收发数据等逻辑。那我们就要基于asio完成这个服务的搭建。主服务是这个样子的

 
  1. #include "LogicSystem.h"
  2. #include <csignal>
  3. #include <thread>
  4. #include <mutex>
  5. #include "AsioIOServicePool.h"
  6. #include "CServer.h"
  7. #include "ConfigMgr.h"
  8. using namespace std;
  9. bool bstop = false;
  10. std::condition_variable cond_quit;
  11. std::mutex mutex_quit;
  12. int main()
  13. {
  14. try {
  15. auto &cfg = ConfigMgr::Inst();
  16. auto pool = AsioIOServicePool::GetInstance();
  17. boost::asio::io_context io_context;
  18. boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
  19. signals.async_wait([&io_context, pool](auto, auto) {
  20. io_context.stop();
  21. pool->Stop();
  22. });
  23. auto port_str = cfg["SelfServer"]["Port"];
  24. CServer s(io_context, atoi(port_str.c_str()));
  25. io_context.run();
  26. }
  27. catch (std::exception& e) {
  28. std::cerr << "Exception: " << e.what() << endl;
  29. }
  30. }

CServer类的声明

 
  1. #include <boost/asio.hpp>
  2. #include "CSession.h"
  3. #include <memory.h>
  4. #include <map>
  5. #include <mutex>
  6. using namespace std;
  7. using boost::asio::ip::tcp;
  8. class CServer
  9. {
  10. public:
  11. CServer(boost::asio::io_context& io_context, short port);
  12. ~CServer();
  13. void ClearSession(std::string);
  14. private:
  15. void HandleAccept(shared_ptr<CSession>, const boost::system::error_code & error);
  16. void StartAccept();
  17. boost::asio::io_context &_io_context;
  18. short _port;
  19. tcp::acceptor _acceptor;
  20. std::map<std::string, shared_ptr<CSession>> _sessions;
  21. std::mutex _mutex;
  22. };

构造函数中监听对方连接

 
  1. CServer::CServer(boost::asio::io_context& io_context, short port):_io_context(io_context), _port(port),
  2. _acceptor(io_context, tcp::endpoint(tcp::v4(),port))
  3. {
  4. cout << "Server start success, listen on port : " << _port << endl;
  5. StartAccept();
  6. }

接受连接的函数

 
  1. void CServer::StartAccept() {
  2. auto &io_context = AsioIOServicePool::GetInstance()->GetIOService();
  3. shared_ptr<CSession> new_session = make_shared<CSession>(io_context, this);
  4. _acceptor.async_accept(new_session->GetSocket(), std::bind(&CServer::HandleAccept, this, new_session, placeholders::_1));
  5. }

AsioIOServicePool

从AsioIOServicePool中返回一个可用的iocontext构造Session,然后将接受的新链接的socket写入这个Session保管。

AsioIOServicePool已经在前面讲解很多次了,它的声明如下

 
  1. #include <vector>
  2. #include <boost/asio.hpp>
  3. #include "Singleton.h"
  4. class AsioIOServicePool:public Singleton<AsioIOServicePool>
  5. {
  6. friend Singleton<AsioIOServicePool>;
  7. public:
  8. using IOService = boost::asio::io_context;
  9. using Work = boost::asio::io_context::work;
  10. using WorkPtr = std::unique_ptr<Work>;
  11. ~AsioIOServicePool();
  12. AsioIOServicePool(const AsioIOServicePool&) = delete;
  13. AsioIOServicePool& operator=(const AsioIOServicePool&) = delete;
  14. // 使用 round-robin 的方式返回一个 io_service
  15. boost::asio::io_context& GetIOService();
  16. void Stop();
  17. private:
  18. AsioIOServicePool(std::size_t size = std::thread::hardware_concurrency());
  19. std::vector<IOService> _ioServices;
  20. std::vector<WorkPtr> _works;
  21. std::vector<std::thread> _threads;
  22. std::size_t _nextIOService;
  23. };

AsioIOServicePool具体实现

 
  1. #include "AsioIOServicePool.h"
  2. #include <iostream>
  3. using namespace std;
  4. AsioIOServicePool::AsioIOServicePool(std::size_t size):_ioServices(size),
  5. _works(size), _nextIOService(0){
  6. for (std::size_t i = 0; i < size; ++i) {
  7. _works[i] = std::unique_ptr<Work>(new Work(_ioServices[i]));
  8. }
  9. //遍历多个ioservice,创建多个线程,每个线程内部启动ioservice
  10. for (std::size_t i = 0; i < _ioServices.size(); ++i) {
  11. _threads.emplace_back([this, i]() {
  12. _ioServices[i].run();
  13. });
  14. }
  15. }
  16. AsioIOServicePool::~AsioIOServicePool() {
  17. std::cout << "AsioIOServicePool destruct" << endl;
  18. }
  19. boost::asio::io_context& AsioIOServicePool::GetIOService() {
  20. auto& service = _ioServices[_nextIOService++];
  21. if (_nextIOService == _ioServices.size()) {
  22. _nextIOService = 0;
  23. }
  24. return service;
  25. }
  26. void AsioIOServicePool::Stop(){
  27. //因为仅仅执行work.reset并不能让iocontext从run的状态中退出
  28. //当iocontext已经绑定了读或写的监听事件后,还需要手动stop该服务。
  29. for (auto& work : _works) {
  30. //把服务先停止
  31. work->get_io_context().stop();
  32. work.reset();
  33. }
  34. for (auto& t : _threads) {
  35. t.join();
  36. }
  37. }

CServer的处理连接逻辑

 
  1. void CServer::HandleAccept(shared_ptr<CSession> new_session, const boost::system::error_code& error){
  2. if (!error) {
  3. new_session->Start();
  4. lock_guard<mutex> lock(_mutex);
  5. _sessions.insert(ma

相关文章:

  • SpringBoot的汽车商城后台管理系统源码开发实现
  • **马小帅面试记:Java技术问答**
  • Win10下安装Linux-Ubuntu24.04双系统
  • 2025-05-04 Unity 网络基础6——TCP心跳消息
  • Android第三次面试总结之Java篇补充
  • NV214NV217美光闪存固态NV218NV225
  • 基于Hive + Spark离线数仓大数据实战项目(视频+课件+代码+资料+笔记)
  • 【LeetCode Hot100】动态规划篇
  • 二叉搜索树实现删除功能 Java
  • 初识 iOS 开发中的证书固定
  • EasyExcel使用总结
  • 【Linux系统】第二节—基础指令(2)
  • 【ArcGIS微课1000例】0144:沿线或多边形要素添加折点,将曲线线段(贝塞尔、圆弧和椭圆弧)替换为线段。
  • Spring MVC设计与实现
  • 【Java JUnit单元测试框架-60】深入理解JUnit:Java单元测试的艺术与实践
  • 架构思维:利用全量缓存架构构建毫秒级的读服务
  • 【C++ Qt】输入类控件(上) LineEdit、QTextEdit
  • 仓颉编程语言快速入门:从零构建全场景开发能力
  • 主成分分析(PCA)与逻辑回归在鸢尾花数据集上的实践与效果对比
  • PyTorch_张量索引操作
  • 言短意长|如何看待“订不到酒店的游客住进局长家”这件事
  • 马斯克“星舰基地”成为新城镇,首任市长为SpaceX员工
  • 经常犯困、迷糊……当心是身体发出的“黄牌”警告
  • 巴菲特首次明确批评贸易战,“投资界春晚”有哪些看点?一文速览
  • 三亚回应“游客骑摩托艇出海遇暴雨”:未失联,已引导申请先行赔付
  • 新华每日电讯头版聚焦上海:科创高地向未来