boost asio tcp简单异步模型0

256 篇文章 3 订阅
149 篇文章 2 订阅

服务端:

#include <iostream>
#include <string>
#include <array>
#include <list>
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include <boost/asio.hpp>
static constexpr size_t MAX_IP_PACK_SIZE = 65536;
static constexpr size_t IP_PACK_HEAD = 4;
static constexpr size_t MAX_CONNECTION_NUM = 128;
class rw_handler {
public:
    rw_handler(boost::asio::io_service &service) : sock_(service) {
    }
    rw_handler(const rw_handler &) = delete;
    rw_handler & operator = (const rw_handler &) = delete;
    ~rw_handler() = default;
public:
    void handle_read() {
        boost::asio::async_read(sock_, boost::asio::buffer(buffer_), boost::asio::transfer_at_least(IP_PACK_HEAD), [this] (const boost::system::error_code &error_code, size_t size) {
            if (error_code) {   // 读出错或者读到不足IP_PACK_HEAD字节
                handle_error(error_code);
                return;
            }
            std::cout << buffer_.data() + IP_PACK_HEAD << std::endl;
            handle_read();
        });
    }
    inline void set_connect_id(int id) {
        connect_id_ = id;
    }
    inline int get_connect_id() const {
        return connect_id_;
    }
    void close_socket() {
        boost::system::error_code error_code;
        sock_.shutdown(boost::asio::ip::tcp::socket::shutdown_send, error_code);
        std::cout << "socket shutdown error message:" << error_code.message() << std::endl;
        sock_.close(error_code);
        std::cout << "socket close error message:" << error_code.message() << std::endl;
    }
    inline boost::asio::ip::tcp::socket &get_socket() {
        return sock_;
    }
    template <typename F>
    inline void set_callback(const F &f) {
        error_callback_fun = f;
    }
private:
    void handle_error(const boost::system::error_code &error_code) {
        close_socket();
        std::cout << "handle_error:" << error_code.message() << std::endl;
        if (nullptr != error_callback_fun) {
            error_callback_fun(connect_id_);
        }
    }
    inline void send_data(const char *data, size_t len) {
        size_t send_len = len > MAX_IP_PACK_SIZE ? MAX_IP_PACK_SIZE : len;
        boost::system::error_code error_code;
        boost::asio::write(sock_, boost::asio::buffer(data, send_len), error_code);
        if (error_code) {
            handle_error(error_code);
        }
    }
private:
    int connect_id_;
    std::array<char, MAX_IP_PACK_SIZE>buffer_;
    std::function<void(int)>error_callback_fun;
    boost::asio::ip::tcp::socket sock_;
};
class server {
public:
    server(boost::asio::io_service &service, short port) : service_(service), 
            acceptor_(service_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
            connect_pool_(MAX_CONNECTION_NUM) {
        int current = 0;
        std::generate_n(begin(connect_pool_), MAX_CONNECTION_NUM, [&current] { return ++current; });
    }
    server(const server &) = delete;
    server & operator = (const server &) = delete;
    virtual ~server() = default;
public:
    void accept() {
        std::cout << "server start listening" << std::endl;
        auto handle = create_handle();
        acceptor_.async_accept(handle->get_socket(), [this, handle] (const boost::system::error_code &error_code) {
            if (error_code) {
                handle_accept_error(handle, error_code);
            }
            handle_map_[handle->get_connect_id()] = handle;
            handle->handle_read();
            accept();
        });
    }
private:
    void recycle_connect_id(int id) {
        auto it = handle_map_.find(id);
        if (it != end(handle_map_)) {
            handle_map_.erase(it);
        }
        std::cout << "current connect count = " << handle_map_.size() << std::endl;
        connect_pool_.push_back(id);
    }
    std::shared_ptr<rw_handler> create_handle() {
        int id = connect_pool_.front();
        connect_pool_.pop_front();
        auto handle = std::make_shared<rw_handler>(service_);
        handle->set_connect_id(id);
        handle->set_callback([this] (int id) {
            recycle_connect_id(id);
        });
        return std::move(handle);
    }
    void stop_acceptor() {
        boost::system::error_code error_code;
        acceptor_.cancel(error_code);
        std::cout << "acceptor cancel error message:" << error_code.message() << std::endl;
        acceptor_.close(error_code);
        std::cout << "acceptor close error message:" << error_code.message() << std::endl;
        service_.stop();
    }
    void handle_accept_error(std::shared_ptr<rw_handler>handle, const boost::system::error_code &error_code) {
        std::cout << "error code:" << error_code.value() << " reason:" << error_code.message() << std::endl;
        handle->close_socket();
        stop_acceptor();                                      
    }
private:
    boost::asio::io_service &service_;
    boost::asio::ip::tcp::acceptor acceptor_;
    std::map<int, std::shared_ptr<rw_handler>>handle_map_;  // key -- connect id
    std::list<int>connect_pool_;
};
class message {
public:
    message() = default;
    ~message() = default;
public:
    inline const char *data() const {
        return data_;
    }
    inline size_t size() const {
        return HEAD_LEN + body_size_;
    }
    inline const char *body() const {
        return data_ + HEAD_LEN;
    }
private:
    static constexpr size_t HEAD_LEN = 4;
    static constexpr size_t MAX_BODY_LEN = 512;
private:
    char data_[HEAD_LEN + MAX_BODY_LEN] = { 0 };
    size_t body_size_ = 0;
};
int main() {
    boost::asio::io_service service;
    server my_server(service, 9901);
    my_server.accept();
    service.run();

    return 0;
}

 

客户端:

#include <netdb.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>

int main(int argc, char* argv[])
{
        if(argc<3)
        {
                printf("usage : %s ip port\n", argv[0]);
                exit(1);
        }

        // create socket
        // tcp
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if(sockfd<0)
        {
                perror("socket error");
                exit(1);
        }

        struct sockaddr_in serveraddr;
        memset(&serveraddr,0, sizeof(serveraddr));
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(atoi(argv[2]));
        inet_pton(AF_INET, argv[1],
                        &serveraddr.sin_addr.s_addr);
        if(connect(sockfd, (struct sockaddr*)&serveraddr,
                                sizeof(serveraddr))<0)
        {
                perror("connect error");
                exit(1);
        }
        while (true) {
                char buffer[1024] = "";
                std::cin >> buffer;
        size_t size = strlen(buffer);
        if(write(sockfd, buffer,size)!=size) {
                perror("write error");
}
        else {
//               char buffer[1024] = "";
//              size = read(sockfd, buffer, sizeof(buffer));
//              std::cout << "client read size = " << size << " read " << buffer << std::endl;
        }
}


        close(sockfd);

        return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Boost.Asio 是一个功能强大的 C++ 库,提供了对网络和底层 I/O 操作的跨平台支持。它可以用于实现 TCP 异步通信。 要使用 Boost.Asio 进行 TCP 异步通信,首先需要创建一个 io_context 对象,它负责处理底层的 I/O 操作。然后,创建一个 tcp::socket 对象,用于建立和管理 TCP 连接。接下来,使用异步操作来进行连接、读取和写入数据。 下面是一个简单的示例代码,展示了如何使用 Boost.Asio 进行 TCP 异步通信: ```cpp #include <iostream> #include <boost/asio.hpp> using boost::asio::ip::tcp; class TcpClient { public: TcpClient(boost::asio::io_context& io_context) : io_context_(io_context), socket_(io_context) {} void Connect(const std::string& host, const std::string& port) { tcp::resolver resolver(io_context_); tcp::resolver::results_type endpoints = resolver.resolve(host, port); boost::asio::async_connect(socket_, endpoints, [this](boost::system::error_code ec, tcp::endpoint endpoint) { if (!ec) { std::cout << "Connected to server: " << endpoint << std::endl; Read(); } else { std::cout << "Failed to connect: " << ec.message() << std::endl; } }); } void Read() { boost::asio::async_read(socket_, boost::asio::buffer(data_, max_length), [this](boost::system::error_code ec, std::size_t length) { if (!ec) { std::cout << "Received data: " << std::string(data_, length) << std::endl; Read(); } else { std::cout << "Failed to read data: " << ec.message() << std::endl; } }); } void Write(const std::string& message) { boost::asio::async_write(socket_, boost::asio::buffer(message), [this](boost::system::error_code ec, std::size_t /*length*/) { if (ec) { std::cout << "Failed to write data: " << ec.message() << std::endl; } }); } private: boost::asio::io_context& io_context_; tcp::socket socket_; enum { max_length = 1024 }; char data_[max_length]; }; int main() { boost::asio::io_context io_context; TcpClient client(io_context); client.Connect("localhost", "1234"); // 发送数据示例 client.Write("Hello, server!"); io_context.run(); return 0; } ``` 在上述示例代码中,`TcpClient` 类负责连接服务器、读取和写入数据。`Connect` 方法通过异步连接操作连接到指定的主机和端口,`Read` 方法通过异步读取操作接收服务器发送的数据,`Write` 方法通过异步写入操作向服务器发送数据。 你可以根据自己的需求修改以上示例代码,以适应你的具体应用场景。希望对你有帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值