当前位置: 首页 > news >正文

ubuntu18.04 vsomeip的编译及使用

1、概述

vsomeip (Vehicle SOME/IP) 是 GENIVI 联盟(现并入 COVESA - Connected Vehicle Systems Alliance)推出的一个开源项目,它实现了 ​​SOME/IP (Scalable service-Oriented MiddlewarE over IP)​​ 协议。这是一个专为汽车和嵌入式系统设计的通信协议,用于支持服务发现、远程过程调用(RPC)和事件通知等功能。

下面是关于 vsomeip 的核心介绍,我用一个表格来汇总其主要特性:

特性维度

说明

​核心功能​

实现了 SOME/IP 协议及其服务发现(Service Discovery)机制

​通信模式​

支持请求/响应(Request/Response)、发布/订阅(Publish/Subscribe)等

​传输协议​

支持 TCP 和 UDP

​内部通信​

通过 Unix 域套接字实现同一设备内进程间的高速通信

​路由管理​

中央路由管理器(Routing Manager)负责消息的路由和分发

​序列化​

vsomeip 自身不处理复杂数据结构的序列化,此部分通常由 CommonAPI 等工具完成

​主要依赖​

Boost 库(特别是 Asio、Thread、System)

​构建系统​

CMake

​配置方式​

使用 JSON 格式的配置文件

​应用领域​

车载信息娱乐系统(IVI)、车身控制、自动驾驶辅助系统等车载网络通信

2、 基本工作原理

vsomeip 的工作核心是 ​​服务(Service)​​ 和 ​​实例(Instance)​​。每个服务都有一个唯一的 Service ID,一个服务可以有多个实例(Instance ID)。通信双方(服务提供者 Consumer)通过 Service ID 和 Instance ID 来识别和定位服务。

其工作流程通常包含:

1.​服务注册与发现 (Service Discovery)​​: 服务提供者启动后,会通过 offer_service方法宣告其提供的服务。客户端则通过request_service和注册​​可用性回调函数​​来发现并监控服务的状态变化。

2.消息传递​​: 建立连接后,双方通过 ​​消息处理程序(Message Handler)​​ 来接收和处理请求或响应。服务端需为特定的 Method ID 注册消息处理器,客户端则发送请求并等待响应。

3、编译

vsomeip依赖Boost,因此我们需要先编译和安装Boost:

 编译步骤:点击跳转

接着,编译和安装vsomeip:

 下载: github下载、csdn下载

cmake -DCMAKE_INSTALL_PREFIX:PATH=/home/gui/gui/build -DBOOST_ROOT=/home/gui/gui/build -DBoost_DIR=/home/gui/gui/build -DENABLE_SIGNAL_HANDLING=1 -DDIAGNOSIS_ADDRESS=0x10 ..
make -j$(nproc)
sudo make install

避坑:

vsomeip-master/implementation/endpoints/src/asio_socket_factory.cpp:27:2: error: extra ‘;’ [-Werror=pedantic]};

解决:

  • 错误位置在asio_socket_factory.cpp代码最后一行的 };,这里多了一个分号,将其删掉便可!

4、demo

//server.cpp
#include <vsomeip/vsomeip.hpp>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <iomanip> 
#include <signal.h>
#include <cstdio>
#define LOG_INF(...) std::fprintf(stdout, __VA_ARGS__), std::fprintf(stdout, "\n")
#define LOG_ERR(...) std::fprintf(stderr, __VA_ARGS__), std::fprintf(stderr, "\n")// 全局常量定义
static vsomeip::service_t service_id = 0x1111;
static vsomeip::instance_t service_instance_id = 0x2222;
static vsomeip::method_t service_method_id = 0x3333;// 全局变量 - 替代类的成员变量
static std::shared_ptr<vsomeip::runtime> rtm_;
static std::shared_ptr<vsomeip::application> app_;
static bool stop_ = false;
static std::mutex mutex_;
static std::condition_variable condition_;
static std::thread stop_thread_;// 函数声明
bool init();
void start();
void stop();
void terminate();
void on_state_cbk(vsomeip::state_type_e _state);
void on_message_cbk(const std::shared_ptr<vsomeip::message>& _request);// 初始化函数
bool init() 
{// 获取vSomeIP运行时并创建应用rtm_ = vsomeip::runtime::get();app_ = rtm_->create_application();// 初始化应用if (!app_->init()) {LOG_ERR("Couldn't initialize application");return false;}// 注册消息处理器回调app_->register_message_handler(service_id, service_instance_id, service_method_id,on_message_cbk);// 注册状态处理器app_->register_state_handler(on_state_cbk);return true;
}// 启动函数
void start() 
{// 启动应用app_->start();
}// 停止线程函数
void stop() 
{std::unique_lock<std::mutex> its_lock(mutex_);while (!stop_) {condition_.wait(its_lock);}std::this_thread::sleep_for(std::chrono::seconds(5));// 停止提供服务app_->stop_offer_service(service_id, service_instance_id);// 注销状态处理器app_->unregister_state_handler();// 注销消息处理器app_->unregister_message_handler(service_id, service_instance_id, service_method_id);// 关闭应用app_->stop();
}// 终止函数
void terminate() 
{std::lock_guard<std::mutex> its_lock(mutex_);stop_ = true;condition_.notify_one();
}// 状态回调函数
void on_state_cbk(vsomeip::state_type_e _state) 
{if (_state == vsomeip::state_type_e::ST_REGISTERED) {// 注册成功后提供服务app_->offer_service(service_id, service_instance_id);}
}// 消息回调函数
void on_message_cbk(const std::shared_ptr<vsomeip::message>& _request) 
{// 打印接收到的数据if (_request && _request->get_payload()) {const vsomeip::payload* payload = _request->get_payload().get();std::string received_data(reinterpret_cast<const char*>(payload->get_data()), payload->get_length());LOG_INF("Received data from client (length: %zu bytes):", payload->get_length());LOG_INF("  String: %s", received_data.c_str());// 以十六进制格式打印数据LOG_INF("  Hex: ");for (uint32_t i = 0; i < payload->get_length(); ++i) {printf("0x%02X ", payload->get_data()[i]);}printf("\n");}// 创建响应std::shared_ptr<vsomeip::message> resp = rtm_->create_response(_request);// 构造返回字符串std::string str("Hello ");str.append(reinterpret_cast<const char*>(_request->get_payload()->get_data()), 0, _request->get_payload()->get_length());// 创建返回负载std::shared_ptr<vsomeip::payload> resp_pl = rtm_->create_payload();std::vector<vsomeip::byte_t> pl_data(str.begin(), str.end());resp_pl->set_data(pl_data);resp->set_payload(resp_pl);// 打印发送的数据LOG_INF("Sending response to client (length: %zu bytes):", str.length());LOG_INF("  String: %s", str.c_str());// 以十六进制格式打印发送的数据LOG_INF("  Hex: ");for (char c : str) {printf("0x%02X ", static_cast<unsigned char>(c));}printf("\n");// 发送响应app_->send(resp);// 完成后终止terminate();
}int main(int argc, char** argv) 
{// 初始化停止线程stop_thread_ = std::thread(stop);// 初始化并启动服务if (init()) {start();// 等待停止线程结束if (stop_thread_.joinable()) {stop_thread_.join();}return 0;} else {return 1;}
}
//client.cpp
#include <vsomeip/vsomeip.hpp>#include <cstdio>
#define LOG_INF(...) fprintf(stdout, __VA_ARGS__), fprintf(stdout, "\n")
#define LOG_ERR(...) fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")// 全局变量代替类的成员变量
static vsomeip::service_t service_id = 0x1111;
static vsomeip::instance_t service_instance_id = 0x2222;
static vsomeip::method_t service_method_id = 0x3333;
static std::shared_ptr<vsomeip::runtime> rtm_;
static std::shared_ptr<vsomeip::application> app_;
static bool is_running = false;void stop();
// 状态回调函数
void on_state_cbk(vsomeip::state_type_e _state) 
{if (_state == vsomeip::state_type_e::ST_REGISTERED) {// 注册成功后请求服务app_->request_service(service_id, service_instance_id);}
}// 可用性回调函数
void on_availability_cbk(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) 
{// 检查是否是我们需要的服务if (service_id == _service && service_instance_id == _instance && _is_available) {// 服务可用,发送请求std::shared_ptr<vsomeip::message> rq = rtm_->create_request();rq->set_service(service_id);rq->set_instance(service_instance_id);rq->set_method(service_method_id);// 创建并设置 payloadstd::shared_ptr<vsomeip::payload> pl = rtm_->create_payload();std::string str("World");std::vector<vsomeip::byte_t> pl_data(std::begin(str), std::end(str));pl->set_data(pl_data);rq->set_payload(pl);LOG_INF("Sending: %s", str.c_str());app_->send(rq);}
}// 消息回调函数
void on_message_cbk(const std::shared_ptr<vsomeip::message>& _response) 
{if (service_id == _response->get_service() && service_instance_id == _response->get_instance()&& vsomeip::message_type_e::MT_RESPONSE == _response->get_message_type()&& vsomeip::return_code_e::E_OK == _response->get_return_code()) {// 获取并打印响应 payloadstd::shared_ptr<vsomeip::payload> pl = _response->get_payload();std::string resp = std::string(reinterpret_cast<const char*>(pl->get_data()), 0, pl->get_length());LOG_INF("Received: %s", resp.c_str());stop();}
}// 初始化函数
bool init() 
{// 获取 runtime 并创建应用rtm_ = vsomeip::runtime::get();app_ = rtm_->create_application();// 初始化应用if (!app_->init()) {LOG_ERR("Couldn't initialize application");return false;}// 注册状态回调app_->register_state_handler(on_state_cbk);// 注册消息处理回调app_->register_message_handler(vsomeip::ANY_SERVICE, service_instance_id, vsomeip::ANY_METHOD, on_message_cbk);// 注册可用性回调app_->register_availability_handler(service_id, service_instance_id, on_availability_cbk);return true;
}// 启动函数
void start() 
{is_running = true;app_->start();is_running = false;
}// 停止函数
void stop() 
{if (app_) {// 注销状态处理器app_->unregister_state_handler();// 注销消息处理器app_->unregister_message_handler(vsomeip::ANY_SERVICE, service_instance_id, vsomeip::ANY_METHOD);// 清除所有处理器app_->clear_all_handler();// 释放服务app_->release_service(service_id, service_instance_id);// 停止应用app_->stop();}is_running = false;
}int main(int argc, char** argv) 
{if (init()) {start();return 0;} else {return 1;}
}
//helloworld-local.json
{"unicast": "127.0.0.1","logging": {"level": "debug","console": "false"},"applications": [{"name": "server","id": "0x4444"},{"name": "client","id": "0x5555"}],"services": [{"service": "0x1111","instance": "0x2222","unreliable": "30509"}],"routing": "server","service-discovery": {"enable": "false"}
}
//1.sh 编译脚本
#!/bin/bash# 编译选项
CXX=g++
CXXFLAGS="-std=c++17 -Wall -Wextra -I."
LDFLAGS="-lvsomeip3 -lpthread"# 源文件和目标文件
SERVICE_SRC="./server.cpp"
CLIENT_SRC="./client.cpp"
SERVICE_TARGET="server"
CLIENT_TARGET="client"# 检查vsomeip是否安装
if ! pkg-config --exists vsomeip3; thenecho "错误: 未找到vsomeip3库。请先安装vsomeip。"exit 1
fi# 添加pkg-config提供的编译和链接选项
CXXFLAGS="$CXXFLAGS $(pkg-config --cflags vsomeip3)"
LDFLAGS="$LDFLAGS $(pkg-config --libs vsomeip3)"# 编译服务端
echo "编译服务端..."
$CXX $CXXFLAGS -o $SERVICE_TARGET $SERVICE_SRC $LDFLAGS# 检查编译是否成功
if [ $? -ne 0 ]; thenecho "服务端编译失败"exit 1
fi# 编译客户端
echo "编译客户端..."
$CXX $CXXFLAGS -o $CLIENT_TARGET $CLIENT_SRC $LDFLAGS# 检查编译是否成功
if [ $? -ne 0 ]; thenecho "客户端编译失败"exit 1
fiecho "编译成功!生成了以下可执行文件:"
echo " - $SERVICE_TARGET"
echo " - $CLIENT_TARGET"

点击扫码加入群聊

觉得有帮助的话,打赏一下呗。。

​           

需要商务合作(定制程序)的欢迎私信!! 

http://www.dtcms.com/a/407918.html

相关文章:

  • 自适应网站价格成都it公司排名
  • 长沙seo网站排名厦门同安网站建设
  • 企业购网站建设小说分销平台
  • langchain概述
  • C++笔记(基础)基于范围的for循环 nullptr,using关键字
  • cpanel 子网站做旅游网站犯法吗
  • 浙江华企做的网站效果如何wordpress弹窗
  • 学做效果图的网站有哪些四川平昌县建设局网站
  • 在国外做黄皮网站违法么软盟软件 app开发公司
  • 建水网站建设网站常用的蓝色
  • 怎么查看网站有没有做301深广纵横设计公司官网
  • 做网站要不要35类商标网龙网络公司招聘
  • 【鸿蒙开源技术共建】用@luvi/lv-markdown-in在HarmonyOS上打造高性能Markdown编辑体验
  • 两学一做网站专栏怎么设置网站建设中期怎么入账
  • Java 中 NIO与传统IO的关系 (附Java IO 流核心类对比表)
  • 阿里巴巴怎么做企业网站南京江北新区楼盘
  • I/O 多路转接之 epoll:高并发服务器的性能利器
  • 呼叫行业群呼模式转手拨模式转型代价分析
  • 手机网站建站价格淘宝网站推广策划方案
  • linux 安装和使用CommonAPI
  • Linux指令和Windows的有啥不一样?咋用的?
  • 操作系统(二) :操作系统运行机制(中断和异常、系统调用)
  • 高精度组合惯导技术与IMU传感器价格及供应商分析
  • 网站文字优化方案网络规划与设计报告总结
  • C++ 拓扑排序
  • Ubuntu 24.04.3搭建redis哨兵模式
  • Swift 入门(一 - 基础语法)
  • GCMSCNN 模块:气相色谱 - 质谱数据的分子特征提取方案
  • 简单网页制作模板图片福州seo兼职
  • 新德通:深耕光通信领域,打造全场景网络连接解决方案