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
- Asio服务端连接管理,实现广播数据
- boost::asio 连接管理1
- boost::asio 连接管理2
- boost::asio 连接管理3
- boost::asio 连接管理4
- boost::asio 连接管理5
- boost::asio 连接管理6
- boost::asio 连接管理7
- boost::asio 连接管理8
- boost::asio 连接管理9
- boost::asio 连接管理10
- boost::asio 连接管理8
- Boost.Asio学习之实现广播ChatRoom
- Boos::asio服务器开发之连接管理
- Boost::asio范例分析 服务端线程池实现
- boost asio 实现一个TCP服务端线程池
- boost::asio 连接管理11 如何关闭连接
- 异步服务端 boost asio
- 2、更新提示
- 数据库--数据库链接池--DBCP连接池配置参数说明
- 嵌入式 mysql_free_version出现长时间不操作会自动关闭连接解决方法(有代码)
- C#数据类型转换
- iOS学习之iOS沙盒(sandbox)机制和文件操作(一)
- Asio服务端连接管理,实现广播数据
- Windows8共享网络让手机上网
- HDU 2577 How to Type DP也可以模拟
- Android之数据库异步加载利器--Loaders
- ruby 异步事件驱动的Ruby Web应用框架 Cramp
- 调试视频网页js脚本的方法
- extern作用详解
- java基础知识01
- RMI-初探