1.环境准备
- Ubuntu 18.04.6 LTS
- c++编译器
- 编译用的cmake
- 相关的库
sudo apt-get install libboost-system1.55-dev libboost-thread1.55-dev libboost-log1.55-dev
sudo apt-get install source-highlight doxygen graphviz
sudo apt-get --no-install-recommends install asciidoc
2.源码下载
git clone https://github.com/COVESA/vsomeip.git
3.源码编译
cd vsomeip
$ mkdir build
$ cd build
$ cmake -DENABLE_SIGNAL_HANDLING=1 ..
$ make
$ make install
具体可以参照源码当中的REAMD文件
安装相关的vsomeip头文件和依赖库.so
4.创建相关测试文件
4.1 创建server 测试文件
- 创建一个someip-example文件目录
- 在里面添加一个sevice_example.cpp文件添加
#include <vsomeip/vsomeip.hpp>
std::shared_ptr<vsomeip::application> app;
int main()
{
app = vsomeip::runtime::get()->create_application("world");
app->init();
app->start();
return 0;
}
简单代码
- 在sevice_example.cpp同目录下添加一个CMakeLists.txt文件
- 编写CMakeLists.txt编译选项内容如下
cmake_minimum_required (VERSION 3.10.2)
project (vSomeIPServiceExample)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(Threads REQUIRED)
include_directories("/usr/local/include/")
link_directories("/usr/local/lib")
include_directories(${VSOMEIP_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIR})
find_package(vsomeip3 REQUIRED)
add_executable(service-example ../sevice_example.cpp)
target_link_libraries(service-example vsomeip3 pthread)
- 执行make 编译可执行程序service-example
4.2 创建client 测试文件
- 添加测试源文件client_example.cpp
- 添加cmake内容编译client_example源文件
- 执行make编译可执行程序
4.3 执行程序
- server端启动
- client端启动
- server接收到client端连接
4.4 提供Request/Response 功能
- server添加代码
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vsomeip/vsomeip.hpp>
#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x0421
std::shared_ptr<vsomeip::application> app;
void on_message(const std::shared_ptr<vsomeip::message> &_request) {
std::shared_ptr<vsomeip::payload> its_payload = _request->get_payload();
vsomeip::length_t l = its_payload->get_length();
// Get payload
std::stringstream ss;
for (vsomeip::length_t i=0; i<l; i++) {
ss << std::setw(2) << std::setfill('0') << std::hex
<< (int)*(its_payload->get_data()+i) << " ";
}
std::cout << "SERVICE: Received message with Client/Session ["
<< std::setw(4) << std::setfill('0') << std::hex << _request->get_client() << "/"
<< std::setw(4) << std::setfill('0') << std::hex << _request->get_session() << "] "
<< ss.str() << std::endl;
// Create response
std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()->create_response(_request);
its_payload = vsomeip::runtime::get()->create_payload();
std::vector<vsomeip::byte_t> its_payload_data;
for (int i=9; i>=0; i--) {
its_payload_data.push_back(i % 256);
}
its_payload->set_data(its_payload_data);
its_response->set_payload(its_payload);
app->send(its_response);
}
int main() {
app = vsomeip::runtime::get()->create_application("World");
app->init();
app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app->start();
return 0;
}
服务端提供 message_handler 和 offer 功能。
register_message_handler函数在 someip/application.hpp 中的定义描述为:
virtual void register_message_handler(service_t _service,
instance_t _instance, method_t _method,
message_handler_t _handler) = 0;
//为指定的 method 或 event 注册处理程序。用户应用程序必须调用此方法来为其注册回调。
//每个服务(SERVICE)、实例(INSTANCE)、方法/事件(METHOD)组合只能注册一个处理程序。
offer_service函数在 \vsomeip-master\interface\vsomeip\application.hpp 中的定义描述为:
virtual void offer_service(service_t _service, instance_t _instance,
major_version_t _major = DEFAULT_MAJOR, minor_version_t _minor =
DEFAULT_MINOR) = 0;
//参数 _service:service标识符;
//参数 _instance:提供的服务实例的实例标识符;
//参数 _major:主服务版本号(默认为0);
//参数 _minor:次服务版本号(默认为0)。
offer_service 函数的作用是将service 注册到 vsomeip 路由组件上,从而使感兴趣的客户端可以看到该服务,因此用户应用程序必须为它提供的每个 service 调用offer_service这个方法。根据配置,service有两种模式,一种是只能在内部网络中可用的,另一种是在内部和外部均可使用。为了向外部网络提供服务, 配置中必须包含提供服务实例的端口,如果没有提供这样的端口配置,服务在设备外部是不可见的。
- client添加代码
#include <iomanip>
#include <iostream>
#include <sstream>
#include <condition_variable>
#include <thread>
#include <vsomeip/vsomeip.hpp>
#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x0421
std::shared_ptr< vsomeip::application > app;
std::mutex mutex;
std::condition_variable condition;
void run() {
std::unique_lock<std::mutex> its_lock(mutex);
condition.wait(its_lock);
std::shared_ptr< vsomeip::message > request;
request = vsomeip::runtime::get()->create_request();
request->set_service(SAMPLE_SERVICE_ID);
request->set_instance(SAMPLE_INSTANCE_ID);
request->set_method(SAMPLE_METHOD_ID);
std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
std::vector< vsomeip::byte_t > its_payload_data;
for (vsomeip::byte_t i=0; i<10; i++) {
its_payload_data.push_back(i % 256);
}
its_payload->set_data(its_payload_data);
request->set_payload(its_payload);
app->send(request);
}
void on_message(const std::shared_ptr<vsomeip::message> &_response) {
std::shared_ptr<vsomeip::payload> its_payload = _response->get_payload();
vsomeip::length_t l = its_payload->get_length();
// Get payload
std::stringstream ss;
for (vsomeip::length_t i=0; i<l; i++) {
ss << std::setw(2) << std::setfill('0') << std::hex
<< (int)*(its_payload->get_data()+i) << " ";
}
std::cout << "CLIENT: Received message with Client/Session ["
<< std::setw(4) << std::setfill('0') << std::hex << _response->get_client() << "/"
<< std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "] "
<< ss.str() << std::endl;
}
void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
std::cout << "CLIENT: Service ["
<< std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
<< "] is "
<< (_is_available ? "available." : "NOT available.")
<< std::endl;
condition.notify_one();
}
int main() {
app = vsomeip::runtime::get()->create_application("Hello");
app->init();
app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);
app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
std::thread sender(run);
app->start();
}
与服务端的代码一样,在客户端代码中我们也需要调用 register_message_handler 注册一个消息处理程序,用来接收服务器对客户端请求的响应。原则上,创建请求消息非常容易。只需通过调用 create_request() 获取请求对象,设置 service ID、instance ID 和 method ID,并在最后将序列化的数据写入payload。在上面这个示例中,我们将 0 到 9 的值写入有效负载(std::vector< vsomeip::byte_t >)。
上述代码中出现 “std::thread sender(run);” 的原因是:当我们尝试将请求从客户端发送给服务时,遇到了一个小问题。在发送消息之前必须启动应用程序(app->start()),因为我们需要一个正在运行的事件循环来处理消息。但是该方法 app->start() 不会返回,因为它内部有正在运行的事件循环。因此,就需要启动一个线程(run),并在此线程中等待 availability 回调的返回,然后再调用app->send(request)。
标签:service,部署,app,payload,SAMPLE,Linux,ID,vsomeip From: https://blog.51cto.com/u_15059356/6186349