C++ Boost::asio使用示例

背景情况

vsomip中使用了boost::asio作为通信框架,所以有必要学习使用一下。
本文不涉及原理。

示例

同步/异步客户端

boost_client.h

#ifndef BOOST_CLIENT_H
#define BOOST_CLIENT_H
#include "boost/asio.hpp"
#define BLOCK_SIZE 64 * 1024
#define POINT 2001
#define IP "127.0.0.1"
using namespace boost::asio;
typedef boost::shared_ptr socket_ptr;

void connect_handler(socket_ptr sock,const boost::system::error_code &ec);
void async_client();
void sync_client();
void fill_buffer(char *s);
int read_data(ip::tcp::socket &sock);
int send_data(ip::tcp::socket &sock);
#endif

boost_client.cpp

#include 
#include 

#include 
#include "boost/asio.hpp"

#include "boost_client.h"

using namespace boost::asio;

void async_client()
{
    io_service service;
    ip::tcp::endpoint ep(ip::address::from_string(IP), POINT);
    socket_ptr sockClient(new ip::tcp::socket(service));
    sockClient->async_connect(ep, boost::bind(connect_handler, sockClient, _1)); //
    service.run();
}

void connect_handler(socket_ptr sock, const boost::system::error_code &ec)
{
    if (ec)
    {
        printf("error code = {%d}\n", ec);
    }
    else
    {
        printf("连接成功\n");
    }
    send_data(*sock.get());
    read_data(*sock.get());
}

/**
 * @brief 同步
 * 
 */
void syncClient()
{
    // 所有asio类都需要io_service对象
    io_service iosev;
    // socket对象
    ip::tcp::socket sock(iosev);
    // 连接端点,这里使用了本机连接,可以修改IP地址测试远程连接
    ip::tcp::endpoint ep(ip::address_v4::from_string(IP), POINT);
    // 连接服务器
    boost::system::error_code ec;
    sock.connect(ep, ec);
    // 如果出错,打印出错信息
    if (ec)
    {
        std::cout << boost::system::system_error(ec).what() << std::endl;
    }
    send_data(sock);
    read_data(sock);
}

int read_data(ip::tcp::socket &sock)
{
    boost::system::error_code ec;
    char buf[BLOCK_SIZE];
    // 接收数据
    memset(buf, 0, BLOCK_SIZE);
    int len = sock.read_some(buffer(buf), ec);//read_until
    std::cout.write(buf, len);
    std::cout << len << std::endl;
}

int send_data(ip::tcp::socket &sock)
{
    boost::system::error_code ec;
    // 发送数据
    // char buf[BLOCK_SIZE];
    // fill_buffer(buf);
    std::string value = "Hello world from client ";

    size_t len = sock.write_some(buffer(value), ec);
    std::cout << "writed " << len << " : " + value << std::endl;

    return len;
}

void fill_buffer(char *s)
{
    for (int i = 0; i < BLOCK_SIZE; i++)
    {
        s[i] = 'a';
    }
}

int main(int argc, char *argv[])
{
    {
        printf("start async conection");
        async_client();
    }
    {
        printf("start sync conection");
        // sync_client();        
    }
    return 0;
}

//g++ boost_client.cpp -lpthread -lboost_system -I/usr/local/include/boost -L/usr/local/lib -o client

同步/异步服务端

boost_service.h

#ifndef BOOST_SERVICE_H
#define BOOST_SERVICE_H
#include "boost/asio.hpp"
#include 
#include 

#define BLOCK_SIZE 64 * 1024
#define POINT 2001
#define IP "127.0.0.1"
using namespace boost::asio;

typedef boost::shared_ptr socket_ptr;

extern io_service service;
extern socket_ptr sock;
void sync_service();
void async_service();
void handle_accept(socket_ptr sock, const boost::system::error_code &err);
void start_accept(socket_ptr sock);
int read_data(ip::tcp::socket &sock);
int send_data(ip::tcp::socket &sock);
#endif

boost_service.cpp

#include "boost/asio.hpp"
#include 
#include 
#include 
#include "boost_service.h"
#include 

using namespace boost::asio;

io_service service;
ip::tcp::endpoint ep(ip::tcp::v4(), POINT); //定义监听商品
ip::tcp::acceptor acc(service, ep);
socket_ptr sock(new ip::tcp::socket(service));

void async_service()
{
    printf("register handle callback...\n");
    start_accept(sock);
    printf("Service runing...\n");
    service.run();
}

void handle_accept(socket_ptr sock, const boost::system::error_code &err)
{
    if (err)
    {
        printf("connection status : failed\n");
    }
    else if (err == error::eof)
    {
        printf("connection status : closed\n");
    }
    else if (err == error::already_connected)
    {
        printf("connection status : successed\n");
    }
    // 从这里开始, 你可以从socket读取或者写入
    read_data(*sock.get());

    socket_ptr sock2(new ip::tcp::socket(service));
    start_accept(sock2);
}

void start_accept(socket_ptr sock)
{
    acc.async_accept(*sock, boost::bind(handle_accept, sock, _1));
}

int read_data(ip::tcp::socket &sock)
{
    boost::system::error_code ec;

    // 从客户端读取数据
    char buf[BLOCK_SIZE];
    int len = sock.read_some(buffer(buf), ec);
    // 或者可以使用read_until读到某个字符为止
    // 或者可以使用某种判断方式循环读取

    if (ec)
    {
        std::cout << boost::system::system_error(ec).what() << std::endl;
    }
    std::cout.write(buf, len);
    std::cout << len << std::endl;

    send_data(sock);
    return len;
}

/**
 * @brief 向客户端发送
 * 
 * @param sock 
 * @return int 
 */
int send_data(ip::tcp::socket &sock)
{
    boost::system::error_code ec;
    std::string value = "Hello world from service ";
    size_t len = sock.write_some(buffer(value), ec);
    if (ec)
    {
        std::cout << boost::system::system_error(ec).what() << std::endl;
    }
    std::cout << "writed " << len << " : " + value << std::endl;
}

void sync_service()
{
    io_service iosev;
    ip::tcp::acceptor acceptor(iosev, ip::tcp::endpoint(ip::tcp::v4(), POINT));
    for (;;)
    {
        // socket对象
        ip::tcp::socket socket(iosev);
        // 等待直到客户端连接进来
        acceptor.accept(socket);
        // 显示连接进来的客户端
        std::cout << "client from: " << socket.remote_endpoint().address() << std::endl;
        read_data(socket);
        //Sleep(1000);
    }
}

int main(int argc, char const *argv[])
{
    {
        async_service();
    }
    {
        // sync_service();
    }
    return 0;
}

//g++ boost_service.cpp -lpthread -lboost_system -I/usr/local/include/boost -L/usr/local/lib -o service

基础环境

环境

系统是在WSL2 Ubuntu20.04版本下编译。对于小白可以看这篇环境搭建文章
boost版本1.75,官方下载地址

编译

编译方法

g++ boost_service.cpp -lpthread -lboost_system -I/usr/local/include/boost -L/usr/local/lib -o service
g++ boost_client.cpp -lpthread -lboost_system -I/usr/local/include/boost -L/usr/local/lib -o client

boost编译及安装

官方文档
网友笔记

参考资料

github传送门
Boost.Asio入门
同步示例

你可能感兴趣的:(C++ Boost::asio使用示例)