boost库在工作(36)网络服务端之六
在上面介绍了管理所有连接的类,这个类主要就是添加新的连接,或者删除不需要的连接。但是管理的类CAllConnect是没有办法知道什么时候添加,什么时候删除的,它需要从接收到连接类里获取得到新的连接,从连接类里获得删除的事件。如下面的代码:
//封装一个服务端类来处理网络。
//软件开发人员: 蔡军生 2013-07-28
//
class CConnect :
public boost::enable_shared_from_this< CConnect >
{
static const int MAX_BUFSIZE = 1024;
public:
CConnect(boost::asio::io_service& ioService, CAllConnect& allConnect)
:m_Socket(ioService),
m_rAllConnect(allConnect),
m_strHit("\r\nResp: ")
{
} boost::asio::ip::tcp::socket& GetSocket(void)
{
return m_Socket;
} //发送的消息。
void PushMsg(const std::string& strMsg)
{
m_QueueMsg.push_back(strMsg);
//
std::vector< boost::asio::const_buffer > vSendBuf;
vSendBuf.push_back(boost::asio::buffer(m_strHit)); if (!m_QueueMsg.empty())
{
vSendBuf.push_back(boost::asio::buffer(m_QueueMsg.front()));
}
boost::asio::async_write(m_Socket,
vSendBuf,
boost::bind(&CConnect::HandleWrite, shared_from_this(),
boost::asio::placeholders::error));
} void Start(void)
{
//添加管理连接集合。
m_rAllConnect.Add(shared_from_this()); m_Socket.async_read_some(boost::asio::buffer(m_chBuffer, MAX_BUFSIZE),
boost::bind(&CConnect::HandleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
} void HandleRead(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
std::vector< boost::asio::const_buffer > vSendBuf;
vSendBuf.push_back(boost::asio::buffer(m_strHit)); if (!m_QueueMsg.empty())
{
vSendBuf.push_back(boost::asio::buffer(m_QueueMsg.front()));
}
vSendBuf.push_back(boost::asio::buffer(m_chBuffer, bytes_transferred));
boost::asio::async_write(m_Socket,
vSendBuf,
boost::bind(&CConnect::HandleWrite, shared_from_this(),
boost::asio::placeholders::error));
}
else
{
//从连接集合里删除自己的连接。
m_rAllConnect.Delete(shared_from_this());
}
} void HandleWrite(const boost::system::error_code& error)
{
if (!error)
{
if (!m_QueueMsg.empty())
{
m_QueueMsg.pop_front();
} m_Socket.async_read_some(boost::asio::buffer(m_chBuffer, MAX_BUFSIZE),
boost::bind(&CConnect::HandleRead, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
//从连接集合里删除自己的连接。
m_rAllConnect.Delete(shared_from_this());
}
}
private:
//
boost::asio::ip::tcp::socket m_Socket; //
boost::array<char, MAX_BUFSIZE> m_chBuffer;
std::string m_strHit;
std::deque< std::string > m_QueueMsg;
//保存所有连接集合。
CAllConnect& m_rAllConnect;
}; //服务器,主要接收新连接,并启动新连接接收数据。
//软件开发人员: 蔡军生 2013-07-28
class CServer
{
public:
//构造函数,主要提供IO服务和端口。
CServer(boost::asio::io_service& ioService, short sPort)
:m_ioService(ioService),
m_acceptor(ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), sPort))
{
//创建一个新连接,用来接收连接进来的客户端表示。
boost::shared_ptr< CConnect > pConnect(new CConnect(m_ioService, m_allConnect));
//做连接准备。
m_acceptor.async_accept(pConnect->GetSocket(),
boost::bind(&CServer::HandleAccept, this, pConnect,
boost::asio::placeholders::error));
} //收到客户端连接进来事件响应。
void HandleAccept(boost::shared_ptr< CConnect > pNewConnect,
const boost::system::error_code& error)
{
if (!error)
{
//在这里可以通知别的连接有新连接进来。
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!");
}); //如果没有错误,对连接进来的连接收发数据。
pNewConnect->Start(); //创建新的连接,以备下一个客户端连接进来。
pNewConnect.reset(new CConnect(m_ioService, m_allConnect));
//做连接准备。
m_acceptor.async_accept(pNewConnect->GetSocket(),
boost::bind(&CServer::HandleAccept, this, pNewConnect,
boost::asio::placeholders::error));
}
} private:
//IO服务
boost::asio::io_service& m_ioService;
//接收器,用来接收新连接进来。
boost::asio::ip::tcp::acceptor m_acceptor; //管理所有连接。
CAllConnect m_allConnect;
}; //
int _tmain(int argc, _TCHAR* argv[])
{
//创建一个IO服务
boost::asio::io_service ioService;
//创建服务器,端口为9001。
CServer server(ioService, 9001); //响应IO服务
ioService.run(); return 0;
}
在类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)网络服务端之六的更多相关文章
- boost库在工作(32)网络服务端之二
在这个例子里,服务器对象主要使用boost::asio::io_service对象,这个对象主要用来构造异步接收数据使用,接着定义boost::asio::ip::tcp::acceptor对象,这个 ...
- boost库在工作(37)网络UDP服务端之七
前面介绍的都是网络TCP的服务器和客户端,其实还有UDP的服务器和客户端,同时也有同步和异步之分.UDP与TCP最大的区别,就是TCP是基于连接的,而UDP是无连接的.这里所谓的连接是指对方中断服务时 ...
- boost库在工作(39)网络UDP异步服务端之九
前面创建的UDP服务器和客户端,都是同步的方式,也就是说当接收数据时,不能参与别的事情执行的.如果在一个只有界面线程的程序里,又不想创建多线程,导致复杂程度的增加,在这种情况之下,我们还有一个方案可以 ...
- boost库在工作(40)串行通讯
现代的计算机技术进步很快,各种的通讯也日新月异,像USB.网络.蓝牙.WIFI等通讯技术飞速地出现,改变了整个计算机的通讯能力,速度已经达到GBit级别.但是有一种最原始的通讯方式,还是保留了30年, ...
- boost库在工作(15)绑定器与函数对象之三
前面已经可以优美地解决两个参数的函数给算法for_each调用了,但是又会遇到这样的一种情况,当需要三个参数或者三个以上的参数给算法for_each调用呢?从STL里的绑定器bind1st,显然是不行 ...
- muduo库源码剖析(二) 服务端
一. TcpServer类: 管理所有的TCP客户连接,TcpServer供用户直接使用,生命期由用户直接控制.用户只需设置好相应的回调函数(如消息处理messageCallback)然后TcpSer ...
- boost库在工作(33)网络服务端之三
在这个例子里,表示服务器与一个客户端的沟通渠道,就是一个连接,封装为类CConnect.它是当服务器接收到一个客户端连接请求之后创建的,主要用来就是管理这个连接的生命周期,以及数据的接收和发送.从生命 ...
- cocos2d-x开发:服务端基础库封装
元旦前面几天都在忙着面试,随后的几天也就一直在做服务端基础库开发方面的工作.对于服务端开发,是很久之前的事情了.那时候我还在大学读书,一直都是在倒腾服务端开发方面的东西,毕业后参加公司工作就是一直从事 ...
- SimpleRpc-客户端与服务端工作模型探讨
前言 本篇文章讲述客户端与服务端的具体设计细节.有细心的小伙伴发现,客户端和服务端的工作方式不一样:服务端是多线程计算模型,利用工作线程完成数据的读取,而客户端是单线程(利用Reactor线程完成数据 ...
随机推荐
- ACM1995
/* 汉诺塔V Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- RabbitMQ 入门 Helloworld -摘自网络
本系列教程主要来自于官网入门教程的翻译,然后自己进行了部分的修改与实验,内容仅供参考. “Hello world” of RabbitMQ 1.Windows下RabbitMQ的安装 下载Erlang ...
- gdb 技巧
现实数组: 比如说要显示a[10]中全部的内容用 p a显示的是地址,用p *a显示的是第一个元素显示全部或某一个:p (int [10])*a或者p *a@10 如果你使用 p *a@3 或 p * ...
- 第二百七十七天 how can I 坚持
开玩笑要有个度,哎,或许这就是缘分,很容易受别人影响吗? 中国人为什么会经常抱怨,不抱怨,挺好. 睡觉,红颜祸水,老婆是要能一起 生活的,不是失去,是上天在帮我,哈哈.
- vector 的resize与reserve
最近遇到一个坑,简单说来是resize与reserve的功能混淆了. 如下: 如果调用resize的化,编译会出错,如果给Text提供默认构造函数,则可以编译通过,最终输出的结果为10. 如果调用re ...
- Mysql数据库插入的中文字段值显示问号的问题解决
最近我使用myeclipse连接mysql数据库查询表中的数据,表中字段值为中文的字段显示问号,查了很多资料将解决方法总结如下: 步骤一:修改mysql数据库的配置文件my.ini或者my-defau ...
- hdu4614Vases and Flowers(线段树,段设置,更新时范围的右边值为变量)
Problem Description Alice is so popular that she can receive many flowers everyday. She has N vases ...
- IntelliJ IDEA 开发工具项目maven管理
今天自己重新部署一下intellij下的项目开发环境,顺便把maven管理项目jar包的方法梳理一下 (1)首先下载apache-maven-3.0.4版本的maven,我自己解压在D:\maven\ ...
- Lucene:信息检索与全文检索
目录 信息检索的概念 信息检索技术的分类 全文检索与数据库查询对比 全文检索工具一般由三部分构成 全文检索中建立索引和进行检索的流程 索引里面究竟存什么 如何创建索引 如何对索引进行检索 Lucene ...
- 部署 instance 到 OVS flat network - 每天5分钟玩转 OpenStack(135)
上一节创建了 OVS flat network,今天我们部署 instance 并验证 flat 网络的连通性. launch 新的 instance "cirros-vm1",网 ...