当前位置: 首页 > 工具软件 > asio2 > 使用案例 >

使用 asio2库 进行进程间通信

沈成天
2023-12-01

一,asio2 网络库 介绍

简单理解 asio2 是一个支持 tcp, udp, http, websocket, rpc, ssl, icmp, serial_port的c++第三方库。项目需要,目前我仅仅用到了rpc 这部分功能,使用它来替换QtRo 实现进程间通信,QtRo 用起来太麻烦,需要接口文件,并称生成对应的代码,还要去继承,实现。这个相对简单点。

https://github.com/zhllxt/asio2

,使用

甭管是客户端还是服务端,定义好 函数后,通过bind 绑定,之后 对端 就可以异步调用了(async_call)。

(1),客户端

//连接服务端
bool RPCClient::run(std::string_view host,std::string_view port)
{
    client.set_default_timeout(std::chrono::seconds(20));

    client.bind_connect([&]()
    {
        if (asio2::get_last_error())
            return;
        if (client.is_started())
        {
            ASIO2_ASSERT(asio2::get_last_error() == rpc::error::in_progress);
        }
        else
        {
            ASIO2_ASSERT(asio2::get_last_error() == rpc::error::not_connected);
        }
    });
    bind();
    return client.start(host, port);
}
//绑定需要提供给服务端的函数
void RPCClient::bind()
{
    client.bind("receiveCloudNormal",&RPCClient::receiveCloudNormal,this);
    client.bind("receiveRun",&RPCClient::receiveRun,this);
    client.bind("receiveStop",&RPCClient::receiveStop,this);
    client.bind("receiveImg",&RPCClient::receiveImg,this);
}

//处理具体的业务
void RPCClient::receiveRun()
{
    std::cout<<"receiveRun "<<" time:"<<getTime()<<std::endl;
}

//调用服务端函数
void RPCClient::sendIsCollision(bool collision)
{
    client.async_call("receiveIsCollision", collision).response([](long long _time){
        std::cout<<"sendIsCollision  response: "<<" time:"<<_time<<std::endl;
    });
    std::cout<<"sendIsCollision "<<" time:"<<getTime()<<std::endl;


}

(2)服务端

//监听 ip 端口
bool RPCServer::run(std::string_view host,std::string_view port)
{
    server.bind_connect([&](auto & session_ptr)
    {
        std::cout<<"client enter : "<<session_ptr->remote_address().c_str()<<" "<< session_ptr->remote_port()<<" "<<session_ptr->local_address().c_str()<<" "<< session_ptr->local_port()<<endl;

    }).bind_start([&]()
    {
        cout<<"start rpc server : "<<server.listen_address().c_str()<<" "<< server.listen_port()<<" "<<asio2::last_error_val()<<" "<< asio2::last_error_msg().c_str()<<endl;
    });
    bind();
    return server.start(host, port);
}

//绑定提供给 客户端的函数
void RPCServer::bind()
{
    server.bind("receiveIsCollision",&RPCServer::receiveIsCollision,this);
}

//访问客户端函数
void RPCServer::sendRun()
{
    server.async_call("receiveRun");
    std::cout<<"sendRun "<<" time:"<<getTime()<<std::endl;
}

三, 注意

(1),如何发送图片,比如opencv Mat

这个库 只支持c++ 内置类型,因此所有自定义类型,最好都要转成c++ 内置类型,发送图片是将mat 编码到了 string里。

//自定义图片 结构体
struct Img
{
    std::string piexl;
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(piexl);
    }
};

//发送图片进行编码
void Widget::on_sendImg_clicked()
{
    if(!imgFile.isEmpty()){
        cv::Mat image = imread(imgFile.toStdString().c_str());

        RPCData::Img img;

        std::vector<unsigned char> buff;
        cv::imencode(".png", image, buff);
        img.piexl.resize(buff.size());
        memcpy(&img.piexl[0], buff.data(), buff.size());

        server->sedImg(img);
    }
}


//收到图片进行解码
void RPCClient::receiveImg(RPCData::Img img)
{
    std::cout<<"receiveImg  "<< img.piexl.size()<< " time:"<<getTime()<<std::endl;

    cv::Mat dstImg(1,img.piexl.size(), CV_8U,(char*)img.piexl.data());
    cv::Mat dst = cv::imdecode(dstImg, CV_LOAD_IMAGE_COLOR);
    imwrite ("dstImg.png",dst);
}

(2),如何发送点云 

//自定义点云 结构体
struct Point{
    Point(){
        x=0.0;
        y=0.0;
        z=0.0;
    }
    Point(float _x,float _y,float _z){
        x=_x;
        y=_y;
        z=_z;
    };

    float x;
    float y;
    float z;
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(x);
        ar(y);
        ar(z);
    }
};

struct CloudNormal{
    std::vector<Point> points;

    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(points);
    }
};

 类似资料: