SOME/IP (Scalable service-Oriented MiddlewarE over IP) 是一种通信协议,主要用于嵌入式系统和车载网络中的服务导向通信。SOME/IP是AUTOSAR(AUTomotive Open System ARchitecture,汽车开放系统架构)标准的一部分,AUTOSAR是由主要汽车制造商和供应商共同制定的开放式汽车电子架构标准。
SOME/IP协议定义了一种基于IP的服务导向的通信机制。在SOME/IP中,服务是一种可以被远程调用的功能,每个服务由一组方法和事件组成。服务由服务ID和实例ID唯一标识,方法和事件由方法ID和事件ID标识。
SOME/IP协议支持一对一、一对多和多对多的通信模式,可以使用UDP或TCP作为传输协议。SOME/IP还支持多播和事件订阅机制,可以有效地支持大规模的设备通信。
SOME/IP消息由一个头部和一个或多个负载部分组成。头部包含了消息的基本信息,如服务ID、实例ID、方法ID、消息类型(请求、请求应答、通知)等。负载部分则包含了实际的数据。
SOME/IP还定义了一种服务发现机制,设备可以通过这种机制来发现网络中可用的服务。这种服务发现机制基于SOME/IP-SD(Service Discovery)协议,是SOME/IP的一个重要组成部分。
总的来说,SOME/IP是一种灵活、可扩展的服务导向通信协议,适用于嵌入式系统和车载网络等环境。
本文主要是在ubuntu PC中部署SOME/IP环境,并编写一些测试程序进行通信测试。
使用some/ip前需要安装一些依赖库如下:
sudo apt-get install libboost-system-dev libboost-thread-dev libboost-log-dev libboost-program-options-dev libboost-test-dev
新建一个目录,并使用命令行打开,然后输入以下命令 获取some/ip的源码,如下:
git clone https://github.com/GENIVI/vsomeip.git
some/ip源码编译并安装到ubuntu中,命令如下:
cd vsomeip
mkdir build
cd build
cmake ..
make
sudo make install
由上面输出截图可知,默认安装some/ip的库和头文件是在 /usr/local/lib/xxxx 和 /usr/local/include/xxx 目录下。
如果熟悉cmake的同学,可执行设置编译参数,可指定 安装路径。
基于上述安装好some/ip后,我们就可以编写测试程序了。
这里编写一个server,实现加法运算,并将结果返回给client;
编写一个client,将要相加的两个数,传递给服务端,并打印 服务端返回的结果值。
新建server.cpp文件,并输入以下内容:
#include
// 定义服务和方法的ID
#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x9ABC
class SampleService {
public:
SampleService() {
app_ = vsomeip::runtime::get()->create_application();
}
void offer_service() {
app_->init();
app_->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app_->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID,
std::bind(&SampleService::on_request, this, std::placeholders::_1));
app_->start();
}
void on_request(const std::shared_ptr<vsomeip::message> &request) {
std::shared_ptr<vsomeip::message> response = vsomeip::runtime::get()->create_response(request);
int a = request->get_payload()->get_data()[0];
int b = request->get_payload()->get_data()[1];
int result = a + b;
std::shared_ptr<vsomeip::payload> payload = vsomeip::runtime::get()->create_payload();
payload->set_data(std::vector<vsomeip::byte_t>{result});
response->set_payload(payload);
app_->send(response);
}
private:
std::shared_ptr<vsomeip::application> app_;
};
int main() {
SampleService service;
service.offer_service();
return 0;
}
新建client.cpp文件,并输入以下内容:
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 定义服务和方法的ID
#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x9ABC
using namespace std;
class SampleClient {
public:
SampleClient() {
app_ = vsomeip::runtime::get()->create_application();
}
void request_service() {
app_->init();
app_->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID,
std::bind(&SampleClient::on_availability, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
app_->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, vsomeip::ANY_METHOD,
std::bind(&SampleClient::on_response, this, std::placeholders::_1));
app_->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
app_->start();
}
void on_availability(vsomeip::service_t service, vsomeip::instance_t instance, bool is_available) {
if (is_available) {
// std::shared_ptr
request = vsomeip::runtime::get()->create_request();
request->set_service(service);
request->set_instance(instance);
request->set_method(SAMPLE_METHOD_ID);
std::shared_ptr<vsomeip::payload> payload = vsomeip::runtime::get()->create_payload();
payload->set_data(std::vector<vsomeip::byte_t>{15, 20}); // 传递两个整数
request->set_payload(payload);
app_->send(request);
int i =0;
/* TEST vsomeip*/
while (1)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "i: " << i << std::endl;
std::shared_ptr<vsomeip::payload> payload = vsomeip::runtime::get()->create_payload();
payload->set_data(std::vector<vsomeip::byte_t>{i++, 20}); // 传递两个整数
request->set_payload(payload);
app_->send(request);
if(i>100)
i = 0;
}
}
}
void on_response(const std::shared_ptr<vsomeip::message> &response) {
if (response) {
int result = response->get_payload()->get_data()[0];
std::cout << "Result: " << result << std::endl;
}
}
private:
std::shared_ptr<vsomeip::application> app_;
std::shared_ptr<vsomeip::message> request;
};
int main() {
SampleClient client;
client.request_service();
return 0;
}
server编译:
g++ server.cpp -o server -lvsomeip3
client编译:(其中-lpthread 是因为用到了一个延时)
g++ client.cpp -o client -lvsomeip3 -lpthread
运行前需要设置以下lib的环境变量,否则会报错,终端临时设置lib环境变量命令如下:
export LD_LIBRARY_PATH=/usr/local/lib/library:$LD_LIBRARY_PATH
注:每次新打开终端都要设置,同学们可自行将这个环境变量添加到 “ ~/.bashrc” 这文件中,这样就会自动设置LD_LIBRARY_PATH环境变量了。
将上述export语句 添加到 “ ~/.bashrc” 文件末尾,然后使用“source ~/.bashrc” 使更改生效,即可。
server运行:
./server
./client
通过上述在ubuntu环境中部署some/ip ,能够对some/ip有个初步的认识,也能进一步扩大我们对some/ip的兴趣。笔者本人更注重于实践运用,对于理论说明就不太感冒。目的只有一个以用为主切入,进行some/ip的使用说明。后续不定期继续说明some/ip的使用。
如有不足,欢迎留言指正。