boost庫在工作(36)網路服務端之六
阿新 • • 發佈:2019-02-09
在上面介紹了管理所有連線的類,這個類主要就是新增新的連線,或者刪除不需要的連線。但是管理的類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呼叫刪除的函式,這樣就達到連線在管理類裡新增和刪除的響應。通過這樣一個集合,就可以管理所有連線,跟所有連線進行通訊,或者刪除某一個連線。