IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> vsomeip-双机通信例子 -> 正文阅读

[网络协议]vsomeip-双机通信例子

参考
(https://github.com/COVESA/vsomeip/wiki/vsomeip-in-10-minutes#prep)
(http://www.voycn.com/article/guanyusomeipdelijie)

简介

someip是位于七层网络协议的会话层,其是车载以太网引入的一个协议.与CAN相比,其只有在接收方有需求时,server端才会给client发送消息,因此会减少总线上的负载率.
在这里插入图片描述
服务是SOME/IP的最核心概念。在一个服务中,定义了Server和Client两个角色:Server提供服务,Client调用服务。对于同一个服务,只能存在一个Server,但可以同时存在多个Client调用服务。server就是一个提供一组method/event/field的接口

  1. Method

在这里插入图片描述
其包含两种:
带response(request/response)(Request/Response methods allow calls with answers.
不带response (fire&forget)(Fire&Forgetmethods do not have answer messages.

  1. event
    在这里插入图片描述
    是server向client发送的单向消息,其是server主动向订阅了相关event的client发送的消息.(Events are simple messages from Server to Client.

  2. field
    在这里插入图片描述
    其包含3部分:
    Getter : Request/Response
    Setter: Request/Response
    Notifier : Events
    上面两种方式的组合,field可以被订阅,用于消息通知,还具有set和get的功能,对消息进行读写操作.(Fields are properties that may include a Getter, a Setter, and a Notification.

Server端

1. 配置文件(vsomeip.json)(/system/etc)

{
	"unicast" : "本机的ip",
	"logging" : {
		"level" : "trace",
		"console" : "true",
		"file" : {
			"enable" : "false"
		},
		"dlt" : "false"
	},
	"applications" : [
		{
           		"name" : "World",
	       		"id" : "0x3489"
        	}
	],
	"services" : [
		{
			"service" : "0x1234",
			"instance" : "0x5678",
			"reliable" : {
				"port" : "40001",
				"enable-magic-cookies" : "false"
			},
			"events" : [
				{
					"event" : "9001",
					"is_field" : "true",
					"update-cycle" : 2000
				},
				{
					"event" : "9002",
					"is_field" : "true",
					"update-cycle" : 2000									
				}
				],
			"eventgroups" : [
				{
					"eventgroup" : "0x5555",
					"events" : [
						"9001",
						"9002"
					]
				}
			]
		}
	],
	"routing" : "vsomeipd",
	"service-discovery" : {
		"enable" : "true",
		"mode" : "unicast",
		"unicast" : [
			"要通信的ip1","要通信的ip2"
		],
		"multicast" : "224.224.224.245",
		"port" : "30490",
		"protocol" : "udp",
		"initial_delay_min" : "10",
		"initial_delay_max" : "100",
		"cyclic_offer_delay":"10000",
		"request_response_delay":"1500"
	}
}

2. 代码

其主要代码:
 1)创建application(world)(vsomeip::runtime::get()->create_application(“World”)),并进行初始化()(app->init())
 2)为特定的service,instance,method/event的消息注册callback(app->register_message_handler())
 3)向路由注册application(world)提供的service(app->offer_service()),为了让其他的application可以发现该service.注:为了向外部网络提供服务,配置必须包含提供的服务实例的端口。如果没有提供这样的端口配置,服务在设备外部是不可见的.
 4)向路由注册application(world)提供的event(app->offer_event()),允许其他application订阅event/field,以及获取和设置field值。
 5)启动消息处理(app->start()),它将阻塞,直到使用stop方法或通过接收信号终止消息处理。它处理通过套接字接收到的消息,并使用注册的回调函数将它们传递给用户应用程序。

#include <condition_variable>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
#include <vsomeip/vsomeip.hpp>

#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x07
#define SAMPLE_EVENTGROUP_ID 0x5555
#define SAMPLE_EVENT_ID 9001
std::shared_ptr<vsomeip::application> app;
std::mutex mutex;
std::condition_variable condition;

void on_filed_message(const std::shared_ptr<vsomeip::message>& _request) {
    std::shared_ptr<vsomeip::payload> its_payload = _request->get_payload();
    std::cout << "SERVICE:Received filed message: " << std::hex << _request->get_method()
              << ". client: " << std::hex << _request->get_client() << ". data: " << std::hex
              << its_payload->get_data() << std::endl;

    // send response
    std::shared_ptr<vsomeip::message> its_response =
        vsomeip::runtime::get()->create_response(_request);
    its_payload = vsomeip::runtime::get()->create_payload();
    const vsomeip::byte_t its_data[] = {0x11};
    its_payload = vsomeip::runtime::get()->create_payload();
    its_payload->set_data(its_data, sizeof(its_data));
    its_response->set_payload(its_payload);
    app->send(its_response, true);
}

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;

    // Send 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, true);

    // Notify event
    const vsomeip::byte_t its_data[] = {0x10};
    its_payload = vsomeip::runtime::get()->create_payload();
    its_payload->set_data(its_data, sizeof(its_data));
    app->notify(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_payload);

    std::cout << "service: notify over!!" << std::endl;
}

int main() {
    app = vsomeip::runtime::get()->create_application("World");

    std::set<vsomeip::eventgroup_t> its_groups;
    its_groups.insert(SAMPLE_EVENTGROUP_ID);

    app->init();
    //注册method的监听
    app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID,
                                  on_message);
   //注册field的监听
    app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID,
                                  on_filed_message);
    app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
    app->offer_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_groups, true);
    app->offer_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID + 1, its_groups, true);
    
    app->start();
}

Client端

1. 配置文件(vsomeip.json)(/system/etc)

{  
   "unicast":"本机的ip",
   "logging":{  
      "level":"trace",
      "console":"true",
      "file":{  
         "enable":"false"
      },
      "dlt":"false"
   },
   "performance-measurement": {
		"enable":"true",
		"client":"true",
		"server":"false",
		"interval":60
   },
	"applications" : [
		{
           		"name" : "Hello",
	       		"id" : "0x1210"
        	}
	],
	"services" :
	[
		{
			"service" : "0x7788",
			"instance" : "0x98",
			"reliable" : {
				"port" : "40004",
				"enable-magic-cookies" : "true"
			},
			"events" : [
				{
					"event" : "90",
					"is_field" : "true"

				},
				{
					"event" : "91",
					"is_field" : "true"

				}
			],
			"eventgroups" : [
				{
					"eventgroup" : "0x333",
					"events" : [
						"90",
						"91"
					]
				}
			]
		}
   ],

	"routing" : "vsomeipd",
	"service-discovery" : {
		"enable" : "true",
		"mode" : "unicast",
		"unicast" : [
			"要通信的ip1","要通信的ip2"
		],
		"multicast" : "224.224.224.245",
		"port" : "30490",
		"protocol" : "udp",
		"initial_delay_min" : "10",
		"initial_delay_max" : "100",
		"cyclic_offer_delay":"10000",
		"request_response_delay":"1500"
   }
}

2. 代码

其主要代码:
1)创建application(world)(vsomeip::runtime::get()->create_application(“Hello”)),并进行初始化()(app->init())
2)向路由中注册一个监听application(world)状态的callback (app->register_state_handler()).当其反馈在路由中注册成功后,去请求service(app->request_service())
3)注册一个要请求的service的状态的监听,当service出现或消失时会被调用(app->register_availability_handler()),当其反馈service可用时,可以创建request( vsomeip::runtime::get()->create_request(true))向service发送消息(app->send()),和向service注册某些event(app->request_event())的监听(app->subscribe())
4)为特定的service,instance,method/event的消息注册callback(app->register_message_handler())
5)开启一个发送消息的线程(std::thread sender(run))
6)启动消息处理(app->start())

#include <condition_variable>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
#include <vsomeip/vsomeip.hpp>

#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x07
#define SAMPLE_EVENTGROUP_ID 0x5555
#define SAMPLE_EVENT_ID 9001

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::set<vsomeip::eventgroup_t> its_groups;
    its_groups.insert(SAMPLE_EVENTGROUP_ID);
    app->request_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID, its_groups, true);
    app->request_event(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENT_ID + 1, its_groups, true);
    app->subscribe(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_EVENTGROUP_ID);

    // Send Request
    std::shared_ptr<vsomeip::message> request;
    request = vsomeip::runtime::get()->create_request(true);
    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, true);
  
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    // send field request
    std::shared_ptr<vsomeip::message> request_filed;
    request_filed = vsomeip::runtime::get()->create_request(true);
    request_filed->set_service(SAMPLE_SERVICE_ID);
    request_filed->set_instance(SAMPLE_INSTANCE_ID);
    request_filed->set_method(SAMPLE_EVENT_ID);
    std::shared_ptr<vsomeip::payload> filed_payload = vsomeip::runtime::get()->create_payload();
    const vsomeip::byte_t its_data[] = {0x12};
    filed_payload->set_data(its_data, sizeof(its_data));
    request_filed->set_payload(filed_payload);
    app->send(request_filed, true);
}

void on_message(const std::shared_ptr<vsomeip::message>& _response) {
    std::stringstream its_message;
    its_message << "CLIENT: received a notification for event [" << std::setw(4)
                << std::setfill('0') << std::hex << _response->get_service() << "." << std::setw(4)
                << std::setfill('0') << std::hex << _response->get_instance() << "." << std::setw(4)
                << std::setfill('0') << std::hex << _response->get_method()
                << "message_type: " << std::hex << static_cast<int>(_response->get_message_type())
                << "] to Client/Session [" << std::setw(4) << std::setfill('0') << std::hex
                << _response->get_client() << "/" << std::setw(4) << std::setfill('0') << std::hex
                << _response->get_session() << "] = ";
    std::shared_ptr<vsomeip::payload> its_payload = _response->get_payload();
    its_message << "(" << std::dec << its_payload->get_length() << ") ";
    for (uint32_t i = 0; i < its_payload->get_length(); ++i)
        its_message << std::hex << std::setw(2) << std::setfill('0')
                    << (int)its_payload->get_data()[i] << " ";
    std::cout << its_message.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;
    if (_is_available) {
        condition.notify_one();
    }
}

void on_state_cbk(vsomeip::state_type_e _state) {
    std::cout << "on_state_cbk, state: " << static_cast<int>(_state) << std::endl;
    if (_state == vsomeip::state_type_e::ST_REGISTERED) {
        //注册成功后请求service,然后等待on_availability的callback
        // we are registered at the runtime now we can request the service
        // and wait for the on_availability callback to be called
        app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
    }
}

int main() {
    app = vsomeip::runtime::get()->create_application("Hello");

    std::set<vsomeip::eventgroup_t> its_groups;
    its_groups.insert(SLAVE_EVENTGROUP_ID);

    app->init();

    //把这个application注册到路由管理器中,on_state_cbk:callback注册结果
    app->register_state_handler(on_state_cbk);

    app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);
    app->register_message_handler(vsomeip::ANY_SERVICE, vsomeip::ANY_INSTANCE, vsomeip::ANY_METHOD,
                                  on_message);
    std::thread sender(run);
    app->start();
}

android.mk

将上述两个代码编译成bin文件,push进设备中执行

cc_binary {
    name: "someipservice_test",
    proprietary: true,
    srcs: [
        "someip_test_service.cpp",
    ],

    include_dirs: [
        "external/v_SomeIP/vsomeip/arm64/include",
        "external/v_SomeIP/boost/arm64/include",
    ],

    shared_libs: [
        "libbase",
        "libvsomeip",
    ],

    cflags: [
        "-Wall",
        "-Wno-unused-parameter",
        "-Werror",
        "-Wunused-variable",
        "-Wno-unused-variable",
        "-Wformat",
        "-Wc++11-narrowing",
    ],
}

 cc_binary {
    name: "someipclient_test",
    proprietary: true,
    srcs: [
        "someip_test_client.cpp",
    ],

    include_dirs: [
        "external/v_SomeIP/vsomeip/arm64/include",
        "external/v_SomeIP/boost/arm64/include",
    ],

    shared_libs: [
        "libbase",
        "libvsomeip",
    ],

    cflags: [
        "-Wall",
        "-Wno-unused-parameter",
        "-Werror",
        "-Wunused-variable",
        "-Wno-unused-variable",
        "-Wformat",
        "-Wc++11-narrowing",
    ],
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:44:24  更:2022-05-11 16:44:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:55:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码