• 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("
    Resp: ")
    	{
    	}
    
    	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调用删除的函数,这样就达到连接在管理类里添加和删除的响应。通过这样一个集合,就可以管理所有连接,跟所有连接进行通讯,或者删除某一个连接。


  • 相关阅读:
    C++解析-外传篇(3):动态内存申请的结果
    C++解析-外传篇(2):函数的异常规格说明
    C++解析-外传篇(1):异常处理深度解析
    C++解析(31):自定义内存管理(完)
    Fisherfaces 算法的具体实现源码
    Philipp Wagner
    人脸识别中截取面部的实现方法
    OpenCV Haar AdaBoost源码改进据说是比EMCV快6倍
    win10系统下载地址
    人脸识别中的检测(在Opencv中加入了QT)
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3236813.html
Copyright © 2020-2023  润新知