车载以太网之要火系列 - 第48篇:郭大侠学SOME/IP (Subscribe订阅):想收通知要订阅,订阅之后随心阅

写在开篇·蓉儿继续挖坑

上回说到,郭靖搞清楚了Find Service------客户端主动问"谁会啥",服务端单播回复。

郭靖合上笔记本,信心满满:"蓉儿,我懂了!Offer是服务端喊'我在这',Find是客户端问'谁在'。双保险,总能找到服务。"

黄蓉咬了口糖葫芦:"那好,我问你------服务找到了,地址也知道了。那车窗位置变化时,车窗怎么主动告诉座舱?"

郭靖一愣:"用Event?之前讲过。"

黄蓉:"对,Event。但客户端怎么告诉服务端'我想收这个Event'?服务端怎么知道要推给谁?"

郭靖摇头。

"这就是Subscribe的用武之地。想收通知要订阅,订阅之后随心阅。 今天就把Subscribe讲透。"

一、Subscribe是什么

黄蓉在白板上写下定义:

Subscribe = 客户端主动告诉服务端"我想订阅某个EventGroup,有通知请推给我"

角色 动作 说明
客户端(如座舱) 发送Subscribe "我想收EventGroup 0x1001的通知,请把我加进推送列表"
服务端(如车窗ECU) 回复SubscribeACK "订阅成功,以后有通知就推给你"

"Subscribe是客户端的'订阅请求'。 你不订阅,服务端不知道要把通知推给谁。"

二、为什么要订阅?Event不能直接广播吗?

郭靖问:"Event不能像Offer一样广播吗?谁想听谁听。"

黄蓉摇头:"Event如果广播,所有ECU都会收到,不管想不想听。 车上几十个ECU,每个ECU都广播自己的Event,网络会被淹没。"

方式 说明 网络负载
广播Event 所有Event发给所有人 高(N个服务 × M个客户端 = N×M条消息)
订阅+单播 只推给订阅了的客户端 低(N个服务 × 订阅数)

"订阅机制的精髓:按需推送,谁订阅给谁。订阅之后更便捷------不用轮询,不用广播轰炸。"

三、EventGroup是什么(复习+深化)

黄蓉在白板上画了EventGroup的结构:

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    车窗服务的EventGroup                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   EventGroup 0x1001(位置相关事件组)                                 │
│   ├── Field Notifier:车窗位置变化(0x8002)                          │
│   ├── Event:车窗防夹触发(0x8003)                                   │
│   └── Event:车窗到位通知(0x8004)                                   │
│                                                                     │
│   EventGroup 0x1002(故障相关事件组)                                 │
│   ├── Event:电机过载(0x8010)                                       │
│   └── Event:霍尔传感器故障(0x8011)                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

"EventGroup是一组相关Event/Notifier的集合。 订阅EventGroup,就一次性订阅了里面所有Event。"

郭靖:"那为什么不一个Event订阅一次?"

黄蓉反问:"你要收位置变化、防夹、到位三个通知,你是想发3次订阅请求,还是发1次?"

"1次......"

"对!EventGroup就是为了减少订阅请求数量。"

四、一个完整的Subscribe报文示例

黄蓉调出一个座舱订阅EventGroup 0x1001的完整报文(按字段分组):

FF FF | 81 00 | 00 00 00 18 | 12 34 | 00 08 | 01 | 01 | 02 | 00 | 01 | 01 | 00 00 | 00 0C | 03 00 | 00 01 | 10 01 | 00 00 00 00

第一步:SOME/IP头部(12字节)

分组 说明
Service ID FF FF SD专用固定ID
Method ID 81 00 SD专用固定Method ID
Length 00 00 00 18 24字节
Client ID 12 34 座舱的ID
Session ID 00 08 第8次请求
Message Type 02 NOTIFICATION

"还是SD消息,FF FF 81 00。"

第二步:SD头部(4字节)

分组 说明
Version 01 SD版本1
Message Type 03 Subscribe(Offer=02,Find=01,Subscribe=03)
Reserved 00 00 保留
Entry Count 00 00 00 01 有1个Entry

第三步:Subscribe Entry

分组 说明
Entry Type 00 06 Subscribe
Length 00 0C 12字节
Service ID 03 00 要订阅的车窗服务
Instance ID 00 01 左前窗实例
EventGroup ID 10 01 订阅的EventGroup
TTL 00 00 00 00 0表示"永久订阅"(直到退订)

五、服务端收到Subscribe后做什么

黄蓉画了车窗ECU收到Subscribe后的处理流程:

复制代码
车窗ECU收到Subscribe报文:
  │
  ├── 解析出:Service ID=0x0300,Instance ID=0x0001,EventGroup=0x1001
  │
  ├── 检查自己有没有这个EventGroup → 有!
  │
  ├── 把座舱(Client ID=0x1234)加入推送列表
  │
  ├── 回复SubscribeACK
  │
  └── 之后,EventGroup 0x1001里的任何Event/Notifier发生,都推给座舱

SubscribeACK报文:

FF FF | 81 00 | 00 00 00 10 | 12 34 | 00 08 | 01 | 01 | 02 | 00 | 01 | 01 | 00 00 | 00 04 | 00 06 | 00 00

六、订阅后的推送流程

黄蓉画了完整的订阅+推送时序图:

复制代码
座舱(客户端)                          车窗ECU(服务端)
      │                                           │
      │  ① Subscribe(订阅EventGroup 0x1001)      │
      │──────────────────────────────────────────>│
      │                                           │
      │  ② SubscribeACK(订阅成功)                │
      │<──────────────────────────────────────────│
      │                                           │
      │                                           │ ③ 车窗位置从50%升到80%
      │                                           │
      │  ④ Notifier(位置变化,0x8002,80%)       │
      │<──────────────────────────────────────────│
      │                                           │
      │                                           │ ⑤ 车窗防夹触发
      │                                           │
      │  ⑥ Event(防夹触发,0x8003)               │
      │<──────────────────────────────────────────│

"订阅一次,收到所有推送。订阅之后更便捷------不用轮询,不用每次都问。"

七、退订:Unsubscribe

郭靖问:"那如果座舱不想收通知了怎么办?"

黄蓉:"Unsubscribe------退订。"

操作 Entry Type 说明
Subscribe 0x0006 订阅
SubscribeACK 0x0007 订阅确认
Unsubscribe 0x0006 + TTL=0 退订(特殊标记)

"Unsubscribe报文和Subscribe结构一样,TTL=0表示'我要退订'。"

八、Subscribe vs Find vs Offer 对比

黄蓉画了一张完整对比表:

对比项 Offer Find Subscribe
谁发起 服务端 客户端 客户端
目的 告知"我会啥" 询问"谁会啥" 订阅"我想收通知"
发送方式 广播 广播 单播(通常)
响应 单播Offer 单播SubscribeACK
Entry Type 0x0001 0x0000 0x0006
SD Message Type 02 01 03

九、SD三驾马车总结

黄蓉在白板上写下了SD的三个核心功能:

功能 一句话 状态
Offer 服务端喊"我会啥" ✅ 已学
Find 客户端问"谁会啥" ✅ 已学
Subscribe 客户端订"我想收" ✅ 刚学

"三驾马车齐了。Offer让客户端知道服务在哪,Find让客户端主动找服务,Subscribe让客户端收通知。"

十、黄蓉的小本本

郭靖翻开她的笔记本,上面写着:

Subscribe核心要点:

1. 客户端主动订阅:告诉服务端"我想收这个EventGroup的通知"

2. 为什么要订阅:Event不广播,只推给订阅者,节省网络带宽

3. EventGroup:一组相关Event的集合,一次订阅收整组通知

4. 订阅流程:Subscribe → SubscribeACK → 推送通知

5. 退订:Unsubscribe(TTL=0)

6. 一句口诀:想收通知要订阅,订阅之后更便捷

写在最后

郭靖合上笔记本:"Subscribe是客户端主动订阅EventGroup。服务端收到后把客户端加入推送列表,之后Event/Notifier一发生就主动推给订阅者。不订阅,不收通知。订阅之后更便捷------不用轮询,不用广播轰炸。"

黄蓉咬了口糖葫芦:"Offer、Find、Subscribe------SD的三驾马车你都学完了。下篇咱们用完整示例把SD的整个流程串一遍。"

郭靖点头。

"下篇预告:抓个SD报文看一看,完整流程不迷路------SD完整抓包示例。"

打完收工,886。

相关推荐
想成为优秀工程师的爸爸1 天前
车载以太网之要火系列 - 第47篇:郭大侠学SOME/IP (Find Service):主动通知未收好,自己寻问自己找
车载以太网·some/ip·自学笔记
想成为优秀工程师的爸爸1 天前
车载以太网之要火系列 - 第46篇:郭大侠学SOME/IP (offer Service):启动时快稍后慢,断断续续哥还在
车载以太网·some/ip·自学笔记
想成为优秀工程师的爸爸2 天前
车载以太网之要火系列 - 第45篇:郭大侠学SOME/IP (Offer Service):上电主动会喊话,Offer告知我会啥
车载以太网·some/ip·自学笔记
虹科汽车电子5 天前
自动驾驶域控开发与测试实践:虹科车载以太网方案赋能L3量产落地
人工智能·自动驾驶·车载以太网·车辆网络通讯测试·自动驾驶域控开发
想成为优秀工程师的爸爸5 天前
车载以太网之要火系列 - 第40篇:郭大侠学SOME/IP - Method vs Event:一个一问一答,一个自己说话
车载以太网·some/ip·自学笔记
想成为优秀工程师的爸爸7 天前
车载以太网之要火系列 - 第37篇:郭大侠学SOME/IP - 玄之又玄谓之道,报文头中藏玄妙
车载以太网·some/ip·自学笔记
想成为优秀工程师的爸爸9 天前
车载以太网之要火系列 - 番外篇4:从DoIP到SOME/IP,一个初学者的“越级碰瓷”
网络协议·车载以太网
想成为优秀工程师的爸爸10 天前
车载以太网之要火系列 - 第35篇:郭大侠学UDS(34/36/37服务)- 环环相扣展神奇,丝滑更新不迷离
网络协议·uds·车载以太网
想成为优秀工程师的爸爸13 天前
车载以太网之要火系列 - 第33篇:郭大侠学UDS(10服务)- 桃花岛内规矩多,模式切换要会说
网络·笔记·网络协议·信息与通信·车载以太网