在上面介绍了管理所有连接的类,这个类主要就是添加新的连接,或者删除不需要的连接。但是管理的类CAllConnect是没有办法知道什么时候添加,什么时候删除的,它需要从接收到连接类里获取得到新的连接,从连接类里获得删除的事件。如下面的代码:

  1. //封装一个服务端类来处理网络。
  2. //软件开发人员: 蔡军生 2013-07-28
  3. //
  4. class CConnect :
  5. public boost::enable_shared_from_this< CConnect >
  6. {
  7. static const int MAX_BUFSIZE = 1024;
  8. public:
  9. CConnect(boost::asio::io_service& ioService, CAllConnect& allConnect)
  10. :m_Socket(ioService),
  11. m_rAllConnect(allConnect),
  12. m_strHit("\r\nResp: ")
  13. {
  14. }
  15.  
  16. boost::asio::ip::tcp::socket& GetSocket(void)
  17. {
  18. return m_Socket;
  19. }
  20.  
  21. //发送的消息。
  22. void PushMsg(const std::string& strMsg)
  23. {
  24. m_QueueMsg.push_back(strMsg);
  25. //
  26. std::vector< boost::asio::const_buffer > vSendBuf;
  27. vSendBuf.push_back(boost::asio::buffer(m_strHit));
  28.  
  29. if (!m_QueueMsg.empty())
  30. {
  31. vSendBuf.push_back(boost::asio::buffer(m_QueueMsg.front()));
  32. }
  33. boost::asio::async_write(m_Socket,
  34. vSendBuf,
  35. boost::bind(&CConnect::HandleWrite, shared_from_this(),
  36. boost::asio::placeholders::error));
  37. }
  38.  
  39. void Start(void)
  40. {
  41. //添加管理连接集合。
  42. m_rAllConnect.Add(shared_from_this());
  43.  
  44. m_Socket.async_read_some(boost::asio::buffer(m_chBuffer, MAX_BUFSIZE),
  45. boost::bind(&CConnect::HandleRead, shared_from_this(),
  46. boost::asio::placeholders::error,
  47. boost::asio::placeholders::bytes_transferred));
  48. }
  49.  
  50. void HandleRead(const boost::system::error_code& error,
  51. size_t bytes_transferred)
  52. {
  53. if (!error)
  54. {
  55. std::vector< boost::asio::const_buffer > vSendBuf;
  56. vSendBuf.push_back(boost::asio::buffer(m_strHit));
  57.  
  58. if (!m_QueueMsg.empty())
  59. {
  60. vSendBuf.push_back(boost::asio::buffer(m_QueueMsg.front()));
  61. }
  62. vSendBuf.push_back(boost::asio::buffer(m_chBuffer, bytes_transferred));
  63. boost::asio::async_write(m_Socket,
  64. vSendBuf,
  65. boost::bind(&CConnect::HandleWrite, shared_from_this(),
  66. boost::asio::placeholders::error));
  67. }
  68. else
  69. {
  70. //从连接集合里删除自己的连接。
  71. m_rAllConnect.Delete(shared_from_this());
  72. }
  73. }
  74.  
  75. void HandleWrite(const boost::system::error_code& error)
  76. {
  77. if (!error)
  78. {
  79. if (!m_QueueMsg.empty())
  80. {
  81. m_QueueMsg.pop_front();
  82. }
  83.  
  84. m_Socket.async_read_some(boost::asio::buffer(m_chBuffer, MAX_BUFSIZE),
  85. boost::bind(&CConnect::HandleRead, shared_from_this(),
  86. boost::asio::placeholders::error,
  87. boost::asio::placeholders::bytes_transferred));
  88. }
  89. else
  90. {
  91. //从连接集合里删除自己的连接。
  92. m_rAllConnect.Delete(shared_from_this());
  93. }
  94. }
  95. private:
  96. //
  97. boost::asio::ip::tcp::socket m_Socket;
  98.  
  99. //
  100. boost::array<char, MAX_BUFSIZE> m_chBuffer;
  101. std::string m_strHit;
  102. std::deque< std::string > m_QueueMsg;
  103. //保存所有连接集合。
  104. CAllConnect& m_rAllConnect;
  105. };
  106.  
  107. //服务器,主要接收新连接,并启动新连接接收数据。
  108. //软件开发人员: 蔡军生 2013-07-28
  109. class CServer
  110. {
  111. public:
  112. //构造函数,主要提供IO服务和端口。
  113. CServer(boost::asio::io_service& ioService, short sPort)
  114. :m_ioService(ioService),
  115. m_acceptor(ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), sPort))
  116. {
  117. //创建一个新连接,用来接收连接进来的客户端表示。
  118. boost::shared_ptr< CConnect > pConnect(new CConnect(m_ioService, m_allConnect));
  119. //做连接准备。
  120. m_acceptor.async_accept(pConnect->GetSocket(),
  121. boost::bind(&CServer::HandleAccept, this, pConnect,
  122. boost::asio::placeholders::error));
  123. }
  124.  
  125. //收到客户端连接进来事件响应。
  126. void HandleAccept(boost::shared_ptr< CConnect > pNewConnect,
  127. const boost::system::error_code& error)
  128. {
  129. if (!error)
  130. {
  131. //在这里可以通知别的连接有新连接进来。
  132. std::set< boost::shared_ptr< CConnect > >& rAll = m_allConnect.GetAllConnect();
  133. std::for_each(rAll.begin(), rAll.end(),
  134. [&](boost::shared_ptr< CConnect > pOther)
  135. {
  136. pOther->PushMsg("Hello!");
  137. });
  138.  
  139. //如果没有错误,对连接进来的连接收发数据。
  140. pNewConnect->Start();
  141.  
  142. //创建新的连接,以备下一个客户端连接进来。
  143. pNewConnect.reset(new CConnect(m_ioService, m_allConnect));
  144. //做连接准备。
  145. m_acceptor.async_accept(pNewConnect->GetSocket(),
  146. boost::bind(&CServer::HandleAccept, this, pNewConnect,
  147. boost::asio::placeholders::error));
  148. }
  149. }
  150.  
  151. private:
  152. //IO服务
  153. boost::asio::io_service& m_ioService;
  154. //接收器,用来接收新连接进来。
  155. boost::asio::ip::tcp::acceptor m_acceptor;
  156.  
  157. //管理所有连接。
  158. CAllConnect m_allConnect;
  159. };
  160.  
  161. //
  162. int _tmain(int argc, _TCHAR* argv[])
  163. {
  164. //创建一个IO服务
  165. boost::asio::io_service ioService;
  166. //创建服务器,端口为9001。
  167. CServer server(ioService, 9001);
  168.  
  169. //响应IO服务
  170. ioService.run();
  171.  
  172. return 0;
  173. }

在类CServer里的函数HandleAccept通知所有其它连接一个消息,如下代码:

std::set< boost::shared_ptr< CConnect > >& rAll =m_allConnect.GetAllConnect();

std::for_each(rAll.begin(),rAll.end(),

[&](boost::shared_ptr<CConnect > pOther)

{

pOther->PushMsg("Hello!");

});

这里使用了一个C11的特性lambda表达式,达到最清楚化的表示。

然后在类CConnect里函数Start里调用管理类添加的函数,在函数HandleRead和HandleWrite调用删除的函数,这样就达到连接在管理类里添加和删除的响应。通过这样一个集合,就可以管理所有连接,跟所有连接进行通讯,或者删除某一个连接。

boost库在工作(36)网络服务端之六的更多相关文章

  1. boost库在工作(32)网络服务端之二

    在这个例子里,服务器对象主要使用boost::asio::io_service对象,这个对象主要用来构造异步接收数据使用,接着定义boost::asio::ip::tcp::acceptor对象,这个 ...

  2. boost库在工作(37)网络UDP服务端之七

    前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...

  3. boost库在工作(39)网络UDP异步服务端之九

    前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的.如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以 ...

  4. boost库在工作(40)串行通讯

    现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...

  5. boost库在工作(15)绑定器与函数对象之三

    前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行 ...

  6. muduo库源码剖析(二) 服务端

    一. TcpServer类: 管理所有的TCP客户连接,TcpServer供用户直接使用,生命期由用户直接控制.用户只需设置好相应的回调函数(如消息处理messageCallback)然后TcpSer ...

  7. boost库在工作(33)网络服务端之三

    在这个例子里,表示服务器与一个客户端的沟通渠道,就是一个连接,封装为类CConnect.它是当服务器接收到一个客户端连接请求之后创建的,主要用来就是管理这个连接的生命周期,以及数据的接收和发送.从生命 ...

  8. cocos2d-x开发:服务端基础库封装

    元旦前面几天都在忙着面试,随后的几天也就一直在做服务端基础库开发方面的工作.对于服务端开发,是很久之前的事情了.那时候我还在大学读书,一直都是在倒腾服务端开发方面的东西,毕业后参加公司工作就是一直从事 ...

  9. SimpleRpc-客户端与服务端工作模型探讨

    前言 本篇文章讲述客户端与服务端的具体设计细节.有细心的小伙伴发现,客户端和服务端的工作方式不一样:服务端是多线程计算模型,利用工作线程完成数据的读取,而客户端是单线程(利用Reactor线程完成数据 ...

随机推荐

  1. Java内部类this$0字段产生的一个bug

    首先查看下面一段代码,我指出了问题代码的所在,读者先自己思考一下这段代码会有什么问题. 这是用clone方法完整拷贝一个二项堆(BinomialHeap)结构的代码.二项堆中包含一个内部类Binomi ...

  2. ORA-15177: cannot operate on system aliases (DBD ERROR: OCIStmtExecute)

    ASM操作的时候,删除一个文件夹,删除不了,报错如下: ASMCMD> ls -l Type Redund Striped Time Sys Name Y IPAP/ ASMCMD> rm ...

  3. 线性模型(1):Perceptron Learning Algorithm (PLA)

    此笔记源于台湾大学林轩田老师<机器学习基石><机器学习技法> (一) PLA算法是基本的binary Classification算法. 一个基本的问题是,对于银行,假设我知道 ...

  4. 数据结构(三)实现AVL树

    AVL树的定义 一种自平衡二叉查找树,中面向内存的数据结构. 二叉搜索树T为AVL树的满足条件为: T是空树 T若不是空树,则TL.TR都是AVL树,且|HL-HR| <= 1 (节点的左子树高 ...

  5. AHOI2013 Round2 Day2 简要题解

    第一题: 第一问可以用划分树或主席树在O(nlog2n)内做出来. 第二问可以用树状数组套主席树在O(nlog2n)内做出来. 我的代码太挫了,空间刚刚卡过...(在bzoj上) 第二题: 分治,将询 ...

  6. Codeforces 372

    A (被装的袋鼠不可以装的袋鼠)贪心,排序,从n/2分成两部分. B 好一道前缀和的题目. C 标准算法不难想,m^2的算法见http://codeforces.com/blog/entry/9907 ...

  7. 通过源码学Java基础:InputStream、OutputStream、FileInputStream和FileOutputStream

    1. InputStream 1.1 说明 InputStream是一个抽象类,具体来讲: This abstract class is the superclass of all classes r ...

  8. UVA 11300 Spreading the Wealth

    题目大意:n个人手中有些金币,每个人可给相邻两个人一些金币,使得最终每个人手中金币数相同,求被转手的金币最少数 m为最终每个人手中的金币数,a1,a2,a3,...,an为每个人开始时手中的金币数,x ...

  9. 转载JQuery 获取设置值,添加元素详解

    转载原地址 http://www.cnblogs.com/0201zcr/p/4782476.html jQuery 获取内容和属性 jQuery DOM 操作 jQuery 中非常重要的部分,就是操 ...

  10. memcached构建集群分析之一

    memcached本身是不支持集群的,集群所关注的容灾.容错.宕机恢复机制统统都没有,实战中需要自己实现容灾机制. memcached集群相比memcached的优势: 巨量数据分布到集群的多台应用主 ...