zoukankan      html  css  js  c++  java
  • asio的网络通讯代码练手

    asio的网络基本模板(单例模式 消息队列 )

     1 // MyAsio.cpp: 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <iostream>
     6 #include <assert.h>
     7 #include "NetMgr.h"
     8 
     9 using namespace DEF;
    10 /*
    11 write by def
    12 技术博客 http://www.cnblogs.com/itdef/ 
    13 技术交流群 群号码:432336863
    14 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
    15 部分老代码存放地点
    16 http://www.oschina.net/code/list_by_user?id=614253
    17 */
    18 
    19 int main()
    20 {
    21     NetMgr& p = NetMgr::Instance();
    22     NetMgr& p1 =NetMgr::Instance();
    23     assert(&p == &p1);
    24     //std::cout << &p << " " << &p1;
    25     p.Start();
    26     return 0;
    27 }
    MyAsio.cpp
      1 #pragma once
      2 #include "Pre.h"
      3 #include <iostream>
      4 #include <atomic>
      5 
      6 #include <boost/asio.hpp>
      7 #include <boost/bind.hpp>
      8 
      9 #include "SyncQueue.h"
     10 
     11 /*
     12 write by def
     13 技术博客 http://www.cnblogs.com/itdef/ 
     14 技术交流群 群号码:432336863
     15 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
     16 部分老代码存放地点
     17 http://www.oschina.net/code/list_by_user?id=614253
     18 */
     19 
     20 NAMESPACEBEGIN(DEF)
     21 using boost::asio::ip::tcp;
     22 
     23 const char MAGIC_CHAR = '|';
     24 
     25 #pragma  pack (push,1)   
     26 struct BufferHead {
     27     char flag;    // should equal '|'
     28     unsigned int bufferLenth;
     29     BufferHead() {
     30         flag = 0;
     31         bufferLenth = 0;
     32     }
     33     BufferHead(char f, unsigned int len) {
     34         flag = f;
     35         bufferLenth = len;
     36     }
     37 };
     38 
     39 struct BufferStruct {
     40     enum {
     41         BUF_MAX_LENTH = 1024 * 2
     42     };
     43     BufferHead head;
     44     char bufBody[BUF_MAX_LENTH];
     45     BufferStruct() {}
     46     BufferStruct(const BufferStruct& b) {
     47         head = b.head;
     48         memcpy(bufBody, b.bufBody, b.head.bufferLenth);
     49     }
     50     char* GetBody() { return bufBody; }
     51     unsigned int GetLength() { return head.bufferLenth; }
     52 };
     53 #pragma pack(pop)    
     54 
     55 class tcp_connection
     56     : public std::enable_shared_from_this<tcp_connection>
     57 {
     58 public:
     59     typedef std::shared_ptr<tcp_connection> pointer;
     60     static pointer create(boost::asio::io_service& io_service, std::shared_ptr<SyncQueue<std::string>> p_messageQueue)
     61     {
     62         return pointer(new tcp_connection(io_service, p_messageQueue));
     63     }
     64     boost::asio::ip::tcp::socket& socket()
     65     {
     66         return socket_;
     67     }
     68     void start();
     69     ~tcp_connection() {
     70         std::cout << std::endl << "Delete tcp_connection=" << --i << std::endl;
     71     }
     72 private:
     73     tcp_connection(boost::asio::io_service& io_service, std::shared_ptr<SyncQueue<std::string>> p_messageQueue)
     74         : socket_(io_service), p_messageQueue_(p_messageQueue)
     75     {
     76         std::cout << "New tcp_connection " << ++i << " times" << std::endl;
     77     }
     78     void handle_read_head(const boost::system::error_code& error,size_t bytes_transferred);
     79     void handle_read_body(const boost::system::error_code& error,size_t bytes_transferred);
     80     boost::asio::ip::tcp::socket socket_;
     81     std::shared_ptr<SyncQueue<std::string>>  p_messageQueue_;
     82     static std::atomic_int  i;
     83     BufferStruct recvBuff_;
     84 };
     85 
     86 class tcp_server
     87 {
     88 public:
     89     tcp_server(boost::asio::io_service& io_service, int port, std::shared_ptr<SyncQueue<std::string>> p_queue);
     90 private:
     91     void start_accept() {
     92         tcp_connection::pointer new_connection =
     93             tcp_connection::create(acceptor_.get_io_service(), p_messageQueue_);
     94         acceptor_.async_accept(new_connection->socket(),
     95             boost::bind(&tcp_server::handle_accept, this, new_connection,
     96                 boost::asio::placeholders::error));
     97     }
     98     void handle_accept(tcp_connection::pointer new_connection,
     99         const boost::system::error_code& error)
    100     {
    101         if (!error)
    102         {
    103             new_connection->start();
    104         }
    105 
    106         start_accept();
    107     }
    108     std::shared_ptr<SyncQueue<std::string>>  p_messageQueue_;
    109     boost::asio::io_service& io_service_;
    110     boost::asio::ip::tcp::acceptor acceptor_;
    111 };
    112 
    113 
    114 
    115 NAMESPACEEND(DEF)
    netasio.h
     1 #include "NetAsio.h"
     2 
     3 using namespace DEF;
     4 /*
     5 write by def
     6 技术博客 http://www.cnblogs.com/itdef/ 
     7 技术交流群 群号码:432336863
     8 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
     9 部分老代码存放地点
    10 http://www.oschina.net/code/list_by_user?id=614253
    11 */
    12 std::atomic_int tcp_connection::i = 0;
    13 tcp_server::tcp_server(boost::asio::io_service& io_service, int port, std::shared_ptr<SyncQueue<std::string>> p_queue):
    14     io_service_(io_service),
    15     acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
    16     p_messageQueue_(p_queue)
    17 {
    18     start_accept();
    19 }
    20 
    21 void tcp_connection::start() {
    22     boost::asio::async_read(socket_, boost::asio::buffer(&recvBuff_.head,sizeof(recvBuff_.head)),
    23         boost::bind(&tcp_connection::handle_read_head, shared_from_this(),
    24             boost::asio::placeholders::error,
    25             boost::asio::placeholders::bytes_transferred));
    26 }
    27 
    28 
    29 //接受包头内容
    30 void DEF::tcp_connection::handle_read_head(const boost::system::error_code& error,
    31     size_t bytes_transferred)
    32 {
    33     if (error == boost::asio::error::eof) {
    34         return;
    35     }else if (error) {
    36         std::cerr << " socket recv head error!! " << error.message() << std::endl;
    37         return;
    38     }
    39     char *pBuf =  recvBuff_.GetBody();
    40     boost::asio::async_read(socket_, boost::asio::buffer(pBuf, recvBuff_.head.bufferLenth),
    41         boost::bind(&tcp_connection::handle_read_body, shared_from_this(),
    42             boost::asio::placeholders::error,
    43             boost::asio::placeholders::bytes_transferred));
    44 }
    45 
    46 void DEF::tcp_connection::handle_read_body(const boost::system::error_code& error,
    47     size_t bytes_transferred)
    48 {
    49     //处理接收过程中的错误
    50     if (error == boost::asio::error::eof) {
    51         return;
    52     }else if (error) {
    53         std::cerr << " socket recv body error!! " << error.message()<<std::endl;
    54         return;
    55     }
    56     //到达此处则接受正常 打印接受内容
    57     //std::cout << "recv body : " << recvBuff_.GetBody() << std::endl;
    58 
    59     //todo 接受内容放入队列 另行处理 避免网络IO影响处理效率
    60     assert(p_messageQueue_ != nullptr);
    61     p_messageQueue_->Put(recvBuff_.GetBody());
    62 
    63     //再次进入异步等待 进行下一次包头的接收
    64     boost::asio::async_read(socket_, boost::asio::buffer(&recvBuff_.head, sizeof(recvBuff_.head)),
    65         boost::bind(&tcp_connection::handle_read_head, shared_from_this(),
    66             boost::asio::placeholders::error,
    67             boost::asio::placeholders::bytes_transferred));
    68 }
    netasio.cpp
     1 #pragma once
     2 #include "pre.h"
     3 #include <boost/asio.hpp>
     4 
     5 #include "SyncQueue.h"
     6 /*
     7 write by def
     8 技术博客 http://www.cnblogs.com/itdef/ 
     9 技术交流群 群号码:432336863
    10 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
    11 部分老代码存放地点
    12 http://www.oschina.net/code/list_by_user?id=614253
    13 */
    14 NAMESPACEBEGIN(DEF)
    15 using boost::asio::ip::tcp;
    16 
    17 class NetMgr {
    18 public:
    19     //单例
    20     static NetMgr&  Instance() {
    21         static NetMgr instance;
    22         return instance;
    23     }
    24     void Start();
    25     
    26 private:
    27     NetMgr() :p_messageQueue_(std::make_shared<SyncQueue<std::string>>(100)) {}
    28     void NetThread(std::shared_ptr<SyncQueue<std::string>> pQueue);
    29     void CommandDispatch(std::shared_ptr<SyncQueue<std::string>> pQueue);
    30     const std::string EXITCOMMAND= "EXIT";
    31     ~NetMgr() {}
    32     std::shared_ptr<SyncQueue<std::string>>  p_messageQueue_;
    33     boost::asio::io_service io_service_;
    34 };
    35 
    36 
    37 
    38 
    39 
    40 
    41 NAMESPACEEND(DEF)
    netmgr.h
     1 #include <thread>
     2 #include <iostream>
     3 #include "NetMgr.h"
     4 #include "NetAsio.h"
     5 
     6 using namespace DEF;
     7 /*
     8 write by def
     9 技术博客 http://www.cnblogs.com/itdef/ 
    10 技术交流群 群号码:432336863
    11 欢迎c c++ windows驱动爱好者 服务器程序员沟通交流
    12 部分老代码存放地点
    13 http://www.oschina.net/code/list_by_user?id=614253
    14 */
    15 void NetMgr::NetThread(std::shared_ptr<SyncQueue<std::string>> pQueue) {
    16     assert(pQueue != nullptr);
    17     boost::asio::io_service& io_s = io_service_;
    18     tcp_server ts(io_s, 9988, pQueue);
    19     io_s.run();
    20 }
    21 
    22 void NetMgr::CommandDispatch(std::shared_ptr<SyncQueue<std::string>> pQueue) {
    23     assert(pQueue != nullptr);
    24     for (int i = 0; i < 11; i++) {
    25         std::string s;
    26         pQueue->Take(s);
    27         std::cout << s << std::endl;
    28     }
    29 
    30 }
    31 
    32 void NetMgr::Start() {
    33     std::thread t1 = std::thread(&NetMgr::NetThread,this, p_messageQueue_);
    34     std::thread t2 = std::thread(&NetMgr::CommandDispatch,this, p_messageQueue_);
    35     std::string input;
    36     std::cout << "Input "" << EXITCOMMAND << "" to exit";
    37     while (std::cin >> input)
    38     {
    39         //todo  add command parse
    40         if (input == EXITCOMMAND) {
    41             break;
    42         }
    43         std::cout << input << std::endl;
    44     }
    45     t1.join();
    46     t2.join();
    47 }
    ntmgr.cpp

     如何优雅的退出是个很麻烦的问题,细节在实际工作需要在慢慢打磨

    运行如图:

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    day25:接口类和抽象类
    vue1
    How the weather influences your mood?
    机器学习实验方法与原理
    How human activities damage the environment
    Slow food
    Brief Introduction to Esports
    Massive open online course (MOOC)
    Online learning in higher education
    Tensorflow Dataset API
  • 原文地址:https://www.cnblogs.com/itdef/p/8516038.html
Copyright © 2011-2022 走看看