Asio tcp异步例子

Asio tcp异步例子1 什么是 asio Asio 是一个用于网络底层 I O 编程的跨平台 C 开发的网络编程库 支持同步与异步的网络开发 2 asio 有哪些优点 简单易用 跨平台 可以用于大型项目中 3 Asio 的 io service 作用 io service 实例同底层操作系统的 IO 服务进行交互 是 asio 框架中的调度器 所有异步 io 事件都是通过它来分发处理的 Io service 提供了两个方法 post 和

//chat_message.h #ifndef CHAT_MESSAGE_HPP #define CHAT_MESSAGE_HPP #include "Header.h" #include 
  
    #include 
   
     #include 
    
      #include 
     
       #include 
      
        #include "stdafx.h" class chat_message { public: enum { header_length = sizeof(Header) }; enum { max_body_length = 512 }; chat_message(){} const char *data() const { return data_; } char *data() { return data_; } std::size_t length() const { return header_length + m_header.bodySize; } const char *body() const { return data_ + header_length; } char *body() { return data_ + header_length; } int type() const { return m_header.type; } std::size_t body_length() const { return m_header.bodySize; } void setMessage(int messageType, const void *buffer, size_t bufferSize) { assert(bufferSize <= max_body_length); m_header.bodySize = bufferSize; m_header.type = messageType; std::memcpy(body(), buffer, bufferSize); std::memcpy(data(), &m_header, sizeof(m_header)); } void setMessage(int messageType, const std::string& buffer) { setMessage(messageType, buffer.data(), buffer.size()); } bool decode_header() { std::memcpy(&m_header, data(), header_length); if (m_header.bodySize > max_body_length) { std::cout << "body size " << m_header.bodySize << " " << m_header.type << std::endl; return false; } return true; } private: char data_[header_length + max_body_length]; Header m_header; }; #endif 
       
      
     
    
  
//Header.h #ifndef FND_STRUCT_HEADER_H #define FND_STRUCT_HEADER_H #include 
  
    struct Header{ int bodySize; int type; }; enum MessageType { MT_BIND_NAME = 1, MT_CHAT_INFO = 2, MT_ROOM_INFO = 3, }; struct BindName{ char name[32]; int nameLen; }; struct ChatInformation { char information[256]; int infoLen; }; struct RoomInformation { BindName name; ChatInformation chat; }; bool parseMessage(const std::string &input, int *type, std::string &outbuffer); #endif //Header.cpp #include "stdafx.h" #include "Header.h" #include 
   
     #include 
    
      #include 
     
       bool parseMessage(const std::string &input, int *type, std::string &outbuffer) { auto pos = input.find_first_of(" "); if (pos == std::string::npos) return false; if (pos == 0) return false; auto command = input.substr(0, pos); if (command == "BindName") { std::string name = input.substr(pos + 1); if (name.size() > 32) return false; if (type) *type = MT_BIND_NAME; BindName bindInfo; bindInfo.nameLen = name.size(); std::memcpy(&(bindInfo.name), name.data(), name.size()); auto buffer = reinterpret_cast 
      
        (&bindInfo); outbuffer.assign(buffer, buffer + sizeof(bindInfo)); return true; } else if (command == "Chat") { std::string chat = input.substr(pos + 1); if (chat.size() > 256) return false; ChatInformation info; info.infoLen = chat.size(); std::memcpy(&(info.information), chat.data(), chat.size()); auto buffer = reinterpret_cast 
       
         (&info); outbuffer.assign(buffer, buffer + sizeof(info)); if (type) *type = MT_CHAT_INFO; return true; } return false; } 
        
       
      
     
    
  
//chat.cpp #include "chat_message.h" #include 
  
    #include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include "stdafx.h" using boost::asio::ip::tcp; typedef std::deque 
             
               chat_message_queue; std::chrono::system_clock::time_point base; class chat_session; typedef std::shared_ptr 
              
                chat_session_ptr; class chat_room { public: chat_room(boost::asio::io_service& io_service) : m_strand(io_service) {} public: void join(chat_session_ptr); void leave(chat_session_ptr); void deliver(const chat_message&); private: boost::asio::io_service::strand m_strand;//strand提供串行执行, 能够保证线程安全, 同时被post或dispatch的方法, 不会被并发的执行. std::set 
               
                 participants_; enum { max_recent_msgs = 100 }; chat_message_queue recent_msgs_; }; class chat_session : public std::enable_shared_from_this 
                
                  { public: chat_session(tcp::socket socket, chat_room &room) : socket_(std::move(socket)),room_(room), m_strand(socket_.get_io_service()){} void start() { room_.join(shared_from_this()); //加入房间 do_read_header();//读取数据包头 } void deliver(const chat_message &msg){ m_strand.post([this,msg]{ bool write_in_progress = !write_msgs_.empty(); write_msgs_.push_back(msg); if (!write_in_progress) { do_write(); } }); } private: void do_read_header(){ auto self(shared_from_this()); boost::asio::async_read( socket_, boost::asio::buffer(read_msg_.data(),chat_message::header_length), //读取头数据8个字节 m_strand.wrap( [this,self](boost::system::error_code ec, std::size_t){ if ( !ec && read_msg_.decode_header()){ do_read_body();//合法的头部的话,进行内容的读取。 } else { std::cout << "player leave the room\n"; room_.leave(shared_from_this()); } })); } void do_read_body() { auto self(shared_from_this()); boost::asio::async_read( socket_, boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),//内容的读取,async_read相当于读取缓存数据,按长度一次读取大小多少,直到读取完成。 m_strand.wrap( [this,self](boost::system::error_code ec, std::size_t) { if (!ec) { handleMessage(); do_read_header(); } else { room_.leave(shared_from_this()); } })); } void handleMessage() { auto n = std::chrono::system_clock::now() - base; std::cout << "i'm in " << std::this_thread::get_id() << " time " << std::chrono::duration_cast 
                 
                   (n).count() << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(3)); if (read_msg_.type() == MT_BIND_NAME) {//设定昵称 const BindName* bind = reinterpret_cast 
                  
                    (read_msg_.body()); m_name.assign(bind->name, bind->name + bind->nameLen); } else if (read_msg_.type() == MT_CHAT_INFO) { const ChatInformation* chat = reinterpret_cast 
                   
                     (read_msg_.body()); m_chatInformation.assign(chat->information, chat->information + chat->infoLen); auto rinfo = buildRoomInfo(); chat_message msg; msg.setMessage(MT_ROOM_INFO,&rinfo, sizeof(rinfo)); room_.deliver(msg); //对当前房间发送消息 } else { } } void do_write() { //发送数据 auto self(shared_from_this()); boost::asio::async_write( socket_, boost::asio::buffer(write_msgs_.front().data(), write_msgs_.front().length()), m_strand.wrap( [this, self](boost::system::error_code ec, std::size_t) { if (!ec) { write_msgs_.pop_front(); if (!write_msgs_.empty()) { do_write(); } } else { room_.leave(shared_from_this()); } })); } tcp::socket socket_; chat_room &room_; chat_message read_msg_; chat_message_queue write_msgs_; std::string m_name; std::string m_chatInformation; boost::asio::io_service::strand m_strand; RoomInformation buildRoomInfo() const { RoomInformation info; info.name.nameLen = m_name.size(); std::memcpy(info.name.name, m_name.data(), m_name.size()); info.chat.infoLen = m_chatInformation.size(); std::memcpy(info.chat.information, m_chatInformation.data(), m_chatInformation.size()); return info; } }; //加入房间 void chat_room::join(chat_session_ptr participant) { m_strand.post([this, participant]{ participants_.insert(participant); for (const auto& msg : recent_msgs_) participant->deliver(msg); //对所有端广播 }); } //离开房间 void chat_room::leave(chat_session_ptr participant) { m_strand.post([this,participant]{ participants_.erase(participant);}); } void chat_room::deliver(const chat_message &msg) { m_strand.post([this, msg]{ recent_msgs_.push_back(msg); while (recent_msgs_.size() > max_recent_msgs) recent_msgs_.pop_front(); for (auto& participant : participants_) participant->deliver(msg); }); } class chat_server { public: chat_server(boost::asio::io_service &io_service, const tcp::endpoint &endpoint) : acceptor_(io_service, endpoint), socket_(io_service), room_(io_service) { do_accept(); } private: void do_accept() { acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { if (!ec) { auto session = std::make_shared 
                    
                      (std::move(socket_), room_); session->start();//新客户端开始接收数据包 } do_accept(); //创建新连接进行等待 }); } tcp::acceptor acceptor_; tcp::socket socket_; chat_room room_; }; int _tmain(int argc, char *argv[]) { try { base = std::chrono::system_clock::now(); boost::asio::io_service io_service; std::list 
                     
                       servers; tcp::endpoint endpoint(tcp::v4(), 9000); servers.emplace_back(io_service, endpoint); std::vector 
                      
                        threadGroup; for(int i = 0; i < 5; ++i) { threadGroup.emplace_back([&io_service, i]{ std::cout << i << " name is " << std::this_thread::get_id() << std::endl; io_service.run();}); } io_service.run(); for(auto& v : threadGroup) v.join(); } catch (std::exception &e) { std::cout << "Exception: " << e.what(); } return 0; } 
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
     
    
  

客户端:

//client.cpp #include "chat_message.h" #include 
  
    #include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include "stdafx.h" using boost::asio::ip::tcp; typedef std::deque 
             
               chat_message_queue; class chat_client { public: chat_client(boost::asio::io_service &io_service, tcp::resolver::iterator endpoint_iterator) : io_service_(io_service), socket_(io_service) { do_connect(endpoint_iterator); } void write(const chat_message &msg) { io_service_.post([this, msg]() { bool write_in_progress = !write_msgs_.empty(); write_msgs_.push_back(msg); if (!write_in_progress) { do_write(); } }); } void close() { io_service_.post([this]() { socket_.close(); }); } private: void do_connect(tcp::resolver::iterator endpoint_iterator) { boost::asio::async_connect( socket_, endpoint_iterator, [this](boost::system::error_code ec, tcp::resolver::iterator) { if (!ec) { do_read_header(); } }); } void do_read_header() { boost::asio::async_read( socket_, boost::asio::buffer(read_msg_.data(), chat_message::header_length), [this](boost::system::error_code ec, std::size_t /*length*/) { if (!ec && read_msg_.decode_header()) { do_read_body(); } else { socket_.close(); } }); } void do_read_body() { boost::asio::async_read( socket_, boost::asio::buffer(read_msg_.body(), read_msg_.body_length()), [this](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { if (read_msg_.body_length() == sizeof(RoomInformation) && read_msg_.type() == MT_ROOM_INFO) { const RoomInformation *info = reinterpret_cast 
              
                (read_msg_.body()); std::cout << "client: '"; assert(info->name.nameLen <= sizeof(info->name.name)); std::cout.write(info->name.name, info->name.nameLen); std::cout << "' says '"; assert(info->chat.infoLen <= sizeof(info->chat.information)); std::cout.write(info->chat.information, info->chat.infoLen); std::cout << "'\n"; } do_read_header(); } else { socket_.close(); } }); } void do_write() { boost::asio::async_write( socket_, boost::asio::buffer(write_msgs_.front().data(), write_msgs_.front().length()), [this](boost::system::error_code ec, std::size_t /*length*/) { if (!ec) { write_msgs_.pop_front(); if (!write_msgs_.empty()) { do_write(); } } else { socket_.close(); } }); } private: boost::asio::io_service &io_service_; tcp::socket socket_; chat_message read_msg_; chat_message_queue write_msgs_; }; int _tmain(int argc, char* argv[]) { try { boost::asio::io_service io_service; tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query("localhost", "9000"); auto endpoint_iterator = resolver.resolve(query); chat_client c(io_service, endpoint_iterator); std::thread t([&io_service]() { io_service.run(); }); char line[chat_message::max_body_length + 1]; // ctrl-d while (std::cin.getline(line, chat_message::max_body_length + 1)) { chat_message msg; auto type = 0; std::string input(line, line + std::strlen(line)); std::string output; if(parseMessage(input, &type, output)) { msg.setMessage(type, output.data(), output.size()); c.write(msg); std::cout << "write message for server " << output.size() << std::endl; } } c.close(); t.join(); } catch (std::exception &e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; } 
               
              
             
            
           
          
         
        
       
      
     
    
  

运行结果:

 

4121383-19c8107568900429.png

图片440.png

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/213825.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午5:34
下一篇 2026年3月18日 下午5:34


相关推荐

  • 在Ubuntu中安装交叉编译器_为什么一直安装中

    在Ubuntu中安装交叉编译器_为什么一直安装中本文讲述了在Ubuntu中安装pycharm的具体步骤准备环境:Ubuntu21.10,Pycharm2021.1.3具体步骤:1.首先下载pycharm:Pycharm官方下载地址我在这里选择的是2021.1.3的专业版,选择下载Linux版本的pycharm下载好的pycharm如图所示:2.右键点击刚刚下载的文件,选择提取到此处3.打开终端,输入cd命令行,进入刚刚解压文件夹下的bin文件夹,命令行是cd文件夹名称,并按回车键cdpycharm-professional-20

    2025年7月23日
    5
  • 数据库设计中关系规范化理论总结怎么写_数据库规范化理论是什么

    数据库设计中关系规范化理论总结怎么写_数据库规范化理论是什么数据库是一门对数据进行有效管理的技术,它研究信息资源如何被安全地储存和如何被高效地利用,它是现代计算机科学的一个重要分支。其中关系数据库是目前被应用最广泛的数据库类型,它看起来类似于一张二维表,通过应用数学的方法来处理数据库中的数据。在关系数据库的设计过程中,最重要的莫过于对数据库的逻辑设计,即针对一个具体的问题,我们应该如何去构造一个适合它的数据库模式。经过科学家的讨论研究,最终形成我们今天所看到的关系数据库的规范化理论。本文通过例举具体事例来探讨关系规范化理论在数据库逻辑设计中的形成和方法。

    2022年10月16日
    5
  • pycharm能配置c语言程序,PyCharm 配置 Gitlab进行项目开发

    pycharm能配置c语言程序,PyCharm 配置 Gitlab进行项目开发1 生成 SSHkey 由于 Windows 本地 Git 仓库和 GitHub 仓库之间的传输是通过 SSH 加密的 所以必须要让 github 仓库认证你 SSHkey 在此之前 必须要生成 SSHkey 本地可以按照 git 服务 百度下 就可以下载 git 安装了之后在 windows 下查看 c 盘 gt 用户 gt 自己的用户名 gt ssh 下是否有 id rsa id rsa pub 文件 如果没有需要手动生成

    2026年3月19日
    2
  • Java设计模式之行为型:迭代器模式

    Java设计模式之行为型:迭代器模式

    2021年10月4日
    44
  • linux 桌面关闭防火墙,Linux关闭防火墙的方法步骤

    linux 桌面关闭防火墙,Linux关闭防火墙的方法步骤windows 操作系统的防火墙好关闭 但是 linux 操作系统防火墙可能有很多新手朋友不会关闭 下面就让学习啦小编教大家 Linux 关闭防火墙的方法吧 Linux 关闭防火墙的方法首先我们打开 linux 操作系统 小编以 fedora 操作系统为例 虽然 linux 提倡命令行操作 但是很多用户可能不是十分习惯 因此很多 linux 操作系统都有桌面图形界面 跟 windows 操作系统很像 也更加方便了我们的操作 我

    2025年11月14日
    4
  • 什么是“养龙虾”,它能帮我们做什么?

    什么是“养龙虾”,它能帮我们做什么?

    2026年3月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号