SOME/IP介绍
SOME/IP 全称是 Scalable service-Oriented MiddlewarE over IP,是车载以太网里常见的一种服务通信协议。它的核心思想是:把车内 ECU 提供的能力抽象成"服务",其他 ECU 或进程通过服务 ID、实例 ID、方法 ID 去调用这些能力。
它不像传统 CAN 信号那样主要按固定报文广播,而是更接近"服务调用模型"。
典型通信对象可以理解为:
shell
Application
-> Service
-> Instance
-> Method / Event / Field
对应到 hello_world 示例:
shell
hello_world_service application: 0x4444
hello_world_client application: 0x5555
service id: 0x1111
instance id: 0x2222
method id: 0x3333
也就是客户端调用服务端的:
shell
Service 0x1111
Instance 0x2222
Method 0x3333
发送 "World",服务端返回 "Hello World"。
SOME/IP 提供什么
SOME/IP 主要支持几类交互模式:
- Request / Response
客户端调用服务端方法,服务端返回结果。
hello_world 就是这个模式:
shell
client -> service: request("World")
service -> client: response("Hello World")
- Fire and Forget
客户端发送请求,但不要求服务端返回 response。 - Event / Notification
服务端周期性或按条件发布事件,客户端订阅后接收通知。
比如车速、温度、传感器状态变化。
- Field
类似一个带 getter、setter、notification 的属性。
shell
get currentSpeed
set targetTemperature
notify currentSpeedChanged
SOME/IP Service Discovery
SOME/IP 通常还会配合 SOME/IP-SD,也就是 Service Discovery。
它解决的问题是:
- 某个服务现在在哪台 ECU 上?
- 它是否在线?
- IP/端口是多少?
- 客户端什么时候可以调用?
常见 SD 消息包括:
- OfferService:服务端声明"我提供这个服务"。
- FindService:客户端查询"谁提供这个服务"。
- SubscribeEventgroup:客户端订阅事件组。
- StopOfferService:服务端停止提供服务。
vSomeIP 和 SOME/IP 的关系
SOME/IP 是协议规范,vSomeIP 是一个 C++ 实现库。
vSomeIP 帮你处理:
- application 注册
- routing manager
- service offer / request
- message 编解码
- payload 传输
- service availability 回调
- method/event handler 分发
- 本地 UDS 或网络 UDP/TCP 传输
- SOME/IP-SD 支持
应用开发者主要写:
shell
app_->offer_service(service_id, instance_id);
app_->request_service(service_id, instance_id);
app_->register_message_handler(...);
app_->send(message);
SOME/IP 报文里有什么
一个 SOME/IP 消息大体包含:
| 字段 | 作用 |
|---|---|
| Service ID | 标识服务 |
| Method ID / Event ID | 标识方法或事件 |
| Length | 后续数据长度 |
| Client ID | 客户端应用 ID |
| Session ID | 会话 ID,用于匹配 request/response |
| Protocol Version | SOME/IP 协议版本 |
| Interface Version | 服务接口版本 |
| Message Type | request、response、notification 等 |
| Return Code | 调用结果 |
| Payload | 业务数据 |
在 hello_world 中,payload 很简单,就是字符串:
shell
request payload: World
response payload: Hello World
实际车载项目里,payload 通常是按 AUTOSAR、ARXML、IDL 或项目约定序列化后的结构体数据。
SOME/IP 的几个关键概念
-
Service ID
标识一个服务类型,例如"车身控制服务""诊断服务""空调服务"。
-
Instance ID
标识服务实例。一个 service 可以有多个 instance,比如左门控制器和右门控制器可能是同一种 service 的不同 instance。
-
Method ID
标识服务里的某个 RPC 方法。
-
Event ID
标识服务发布的某个事件。
-
Eventgroup
事件组。客户端通常订阅 eventgroup,而不是单个 event。
-
Client ID
标识调用方 application。
-
Session ID
用于区分不同请求,帮助把 response 对回 request。
HelloWorld解析
演示的是 vSomeIP 的最小 request/response 通信流程:服务端 hello_world_service 提供 0x1111.0x2222 服务,客户端 hello_world_client 等待服务可用后调用 method 0x3333,发送 payload World,服务端回复 Hello World。它覆盖了 runtime/application 初始化、handler 注册、offer service、request service、服务可用通知、SOME/IP message/payload 构造、本地 routing manager 通信和优雅停止流程。
对象关系图
## 时序图

SOME/IP vs Fast-DDS
SOME/IP 更像"车载服务调用协议",核心是 service / instance / method / event;
Fast-DDS 更像"分布式数据总线",核心是 topic / publisher / subscriber / data type / QoS。
在车载里可以粗略理解为:
shell
SOME/IP: 谁提供某个服务?我调用它的方法,或订阅它的事件。
Fast-DDS: 谁在发布某类数据?我订阅这个 Topic,持续接收数据流。
核心模型对比
| 维度 | SOME/IP | Fast-DDS |
|---|---|---|
| 标准/协议 | AUTOSAR 常用服务通信协议 | DDS 标准的一种实现,底层常用 RTPS |
| 通信模型 | 面向服务 Service-Oriented | 面向数据 Data-Centric Publish/Subscribe |
| 基本对象 | Service、Instance、Method、Event、Field | Domain、Topic、DataWriter、DataReader、Participant |
| 常见交互 | Request/Response、Event Notification、Fire-and-Forget | Publish/Subscribe,也支持 Request/Reply 模式但不是主模型 |
| 接口标识 | 数字 ID:Service ID、Instance ID、Method ID | Topic 名称 + 数据类型 |
| 数据契约 | 通常来自 AUTOSAR ARXML、接口文档、手写协议 | 通常来自 IDL,生成强类型代码 |
| 发现机制 | SOME/IP-SD:OfferService、FindService、SubscribeEventgroup | DDS Discovery:Participant、Endpoint、Topic 自动发现 |
| QoS 能力 | 相对有限,更多依赖应用和配置 | 很强:可靠性、持久性、历史深度、deadline、liveliness 等 |
| 序列化 | SOME/IP payload 本身偏字节载荷,业务自定义 | DDS/CDR 序列化,强类型数据 |
| 典型场景 | AUTOSAR Adaptive、车载服务调用、ECU 间 RPC | ROS 2、机器人、中间件数据总线、复杂分布式系统 |
实时性
如果只谈"能不能做实时通信",SOME/IP 和 Fast-DDS 都可以用于实时或准实时系统;但它们的实时性侧重点不同:
shell
SOME/IP: 更偏确定的服务调用路径,适合车载控制服务、状态服务、RPC/事件通知。
Fast-DDS: 更偏高频数据分发,适合多订阅者、大量数据流、复杂 QoS 控制。
更直白一点:
shell
低频/中频服务调用、车载 ECU 服务接口 -> SOME/IP 更自然
高频数据流、多消费者、QoS 细粒度控制 -> Fast-DDS 更强
延迟对比
| 维度 | SOME/IP | Fast-DDS |
|---|---|---|
| 通信模型 | 服务调用、事件通知 | Topic 发布订阅 |
| 典型延迟 | 低,但依赖 routing、传输、序列化和服务发现配置 | 低,RTPS/DDS 实现可针对低延迟优化 |
| 本地进程间通信 | vSomeIP 可走 Unix Domain Socket,本机很快 | Fast-DDS 可用共享内存传输,进程间大数据优势明显 |
| 网络通信 | UDP/TCP | UDP/RTPS,部分实现支持 TCP/共享内存 |
| 大数据传输 | 不是强项,payload 自己管理 | 更强,尤其配合共享内存和零拷贝能力 |
| 小 RPC 调用 | 很适合 | 可以做,但不是最原生模型 |
| 高频流式数据 | 可以用 event,但 QoS 和数据总线能力较弱 | 适合,高频发布订阅是强项 |
抖动对比
实时系统不只看平均延迟,还要看抖动,也就是每次通信耗时是否稳定。
| 维度 | SOME/IP | Fast-DDS |
|---|---|---|
| 抖动来源 | routing manager、线程调度、TCP/UDP、服务端处理时间 | discovery、QoS、可靠传输重发、队列深度、线程调度 |
| 可控性 | 配置相对简单,路径清晰 | QoS 很强,但配置不当会引入额外抖动 |
| 可靠模式影响 | TCP 或应用层处理可能增加等待 | Reliable QoS、History、Durability 可能增加延迟和抖动 |
| Best effort 模式 | UDP event 可较轻 | BestEffort + KeepLast 可做到很低延迟 |
Fast-DDS 的 QoS 是双刃剑:
配置得好,可以更贴近实时需求;配置得重,比如可靠传输、历史缓存、持久化、较大队列,会让延迟和抖动上升。
编译vsomeip
boost 1.75.0
shell
$ ./bootstrap.sh
$ ./b2
$ sudo ./b2 install
编译vsome/ip
shell
$ git clone https://github.com/COVESA/vsomeip.git
$ git checkout -b 3.6.4 3.6.4
$ mkdir build && cd build
$ cmake ..
$ make -j4
中间会有编译错误, 注释掉-Werror和-Wno-inconsistent-missing-override
为什么选择3.6.4版本
系统使用Ubuntu 20.04, gcc版本是9.4.0, 支持的C++标准是C++17, 而master最新依赖C++20.