動態

詳情 返回 返回

C++ Boost::asio使用示例 - 動態 詳情

背景情況

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

示例

服務端
image.png
客户端
image.png

同步/異步客户端

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<ip::tcp::socket> 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 <iostream>
#include <string>

#include <boost/bind.hpp>
#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 <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

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

typedef boost::shared_ptr<ip::tcp::socket> 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 <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include "boost_service.h"
#include <string>

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入門
同步示例

Add a new 評論

Some HTML is okay.