Asio服务端连接管理,实现广播数据

来源:互联网 发布:养哈士奇 知乎 编辑:程序博客网 时间:2024/05/17 05:05
#ifndef MESSAGE_H#define MESSAGE_H#include <stdio.h>#include <string.h>#include <stdlib.h>class Message{public:enum { header_length = 4 };enum { max_body_length = 512 };Message(): body_length_(0){}const char* data() const{return data_;}char* data(){return data_;}size_t length() const{return header_length + body_length_;}const char* body() const{return data_ + header_length;}char* body(){return data_ + header_length;}size_t body_length() const{return body_length_;}void body_length(size_t new_length){body_length_ = new_length;if (body_length_ > max_body_length)body_length_ = max_body_length;}bool decode_header(){char header[header_length + 1] = "";strncat(header, data_, header_length);body_length_ = atoi(header);if (body_length_ > max_body_length){body_length_ = 0;return false;}return true;}void encode_header(){char header[header_length + 1] = "";sprintf(header, "%4d", body_length_);memcpy(data_, header, header_length);}private:char data_[header_length + max_body_length];size_t body_length_;};#endif
#ifndef RW_HANDLER_H#define RW_HANDLER_H#include <boost/asio.hpp>#include <boost/bind.hpp>#include <boost/shared_ptr.hpp>#include <boost/enable_shared_from_this.hpp>using namespace boost::asio::ip;using namespace boost::asio;using namespace std;const int MAX_IP_PACK_SIZE = 65536;const int HEAD_LEN = 4;class RWHandler //: public boost::enable_shared_from_this<RWHandler>, private boost::noncopyable{public:RWHandler(io_service& ios) : m_sock(ios){}~RWHandler(){}void HandleRead(){//三种情况下会返回:1.缓冲区满;2.transfer_at_least为真(收到特定数量字节即返回);3.有错误发生async_read(m_sock, buffer(m_buff), transfer_at_least(HEAD_LEN), [this](const boost::system::error_code& ec, size_t size){if (ec != nullptr){HandleError(ec);return;}cout << m_buff.data() + HEAD_LEN << endl;HandleRead();});}void HandleWrite(char* data, int len){//boost::system::error_code ec;//write(m_sock, buffer(data, len), ec);//if (ec != nullptr)//HandleError(ec);}tcp::socket& GetSocket(){return m_sock;}void CloseSocket(){boost::system::error_code ec;m_sock.shutdown(tcp::socket::shutdown_send, ec);m_sock.close(ec);}void SetConnId(int connId){m_connId = connId;}int GetConnId() const{return m_connId;}template<typename F>void SetCallBackError(F f){m_callbackError = f;}void asyn_broadcast(){printf("asyn write someting to every client\n");boost::system::error_code ec;char data[1024] = "give me five";write(m_sock, buffer(data, strlen(data) + 1), ec);if (ec != nullptr)HandleError(ec);}private:void HandleError(const boost::system::error_code& ec){CloseSocket(); cout << ec.message() << endl;if (m_callbackError)m_callbackError(m_connId);}private:tcp::socket m_sock;std::array<char, MAX_IP_PACK_SIZE> m_buff; int m_connId;std::function<void(int)> m_callbackError;};#endif
#ifndef SERVER_H#define SERVER_H#include "Message.h"#include "RWHandler.h"#include <boost/asio/buffer.hpp>#include <boost/unordered_map.hpp>#include <boost/thread.hpp>#include <boost/thread/mutex.hpp>const int MaxConnectionNum = 65536;const int MaxRecvSize = 65536;class Server //: public boost::enable_shared_from_this<RWHandler>, private boost::noncopyable{public:Server(io_service& ios, short port) : m_ios(ios), m_acceptor(ios, tcp::endpoint(tcp::v4(), port)), m_cnnIdPool(MaxConnectionNum){m_isBroadcast = false;int current = 0;std::generate_n(m_cnnIdPool.begin(), MaxConnectionNum, [¤t]{return ++current; });}~Server(){}void Accept(){cout << "Start Listening " << endl;std::shared_ptr<RWHandler> handler = CreateHandler();m_acceptor.async_accept(handler->GetSocket(), [this, handler](const boost::system::error_code& error){if (error){cout << error.value() << " " << error.message() << endl;HandleAcpError(handler, error);}m_mutex.lock();m_handlers.insert(std::make_pair(handler->GetConnId(), handler));cout << "current connect count: " << m_handlers.size() << endl;m_mutex.unlock();handler->HandleRead();Accept();});if(!m_isBroadcast){boost::thread threadBroadcast(BroadcastMessage, this);}}private:void HandleAcpError(std::shared_ptr <RWHandler> eventHanlder, const boost::system::error_code& error){cout << "Error,error reason:" << error.value() << error.message() << endl;//关闭socket,移除读事件处理器eventHanlder->CloseSocket();StopAccept();}void StopAccept(){boost::system::error_code ec;m_acceptor.cancel(ec);m_acceptor.close(ec);m_ios.stop();}std::shared_ptr<RWHandler> CreateHandler(){int connId = m_cnnIdPool.front();m_cnnIdPool.pop_front();std::shared_ptr<RWHandler> handler = std::make_shared<RWHandler>(m_ios);handler->SetConnId(connId);handler->SetCallBackError([this](int connId){        RecyclConnid(connId);});return handler;}void RecyclConnid(int connId){m_mutex.lock();auto it = m_handlers.find(connId);if (it != m_handlers.end())m_handlers.erase(it);cout << "current connect count: " << m_handlers.size() << endl; m_cnnIdPool.push_back(connId);m_mutex.unlock();}static unsigned int BroadcastMessage(void* pThis){Server* pServer = (Server*)pThis;while(true){pServer->m_mutex.lock();//Broadcasting messages to every client.for ( auto it = pServer->m_handlers.begin(); it != pServer->m_handlers.end(); ++it ){//std::cout << " " << it->first << ":" << it->second;it->second->asyn_broadcast();}pServer->m_mutex.unlock();printf("\n");Sleep(1000);}return 0;}private:io_service& m_ios;tcp::acceptor m_acceptor;    boost::unordered_map<int, std::shared_ptr<RWHandler>> m_handlers;list<int> m_cnnIdPool;bool m_isBroadcast;boost::mutex m_mutex;};#endif
//#include "Message.h"//#include "RWHandler.h"#include "Server.h"int main(int argc, char* argv[]){boost::asio::io_service ios;//boost::asio::io_service::work work(ios);//std::thread thd([&ios]{ios.run(); }); Server server(ios, 8100);server.Accept();ios.run();//thd.join();return 0;}




0 0
原创粉丝点击