写在开篇·蓉儿继续挖坑
上回说到,郭靖搞清楚了Offer Service------服务端上电后主动广播"我会啥,我在这"。
郭靖合上笔记本,信心满满:"蓉儿,我懂了!服务端上电就喊话,客户端等着收就行了。"
黄蓉咬了口糖葫芦:"那好,我问你------如果座舱启动晚了,没听到车窗服务的Offer,怎么办?"
郭靖一愣:"这......等下一波?"
黄蓉:"下一波要等1.5秒(重复期)甚至3秒(稳定期)。座舱等得起吗?"
郭靖摇头。
"这就是Find Service的用武之地。 今天就把Find Service 讲透------主动通知未收到,自己寻问自己要。"
一、Find Service是什么
黄蓉在白板上写下定义:
Find Service = 客户端主动广播"谁提供XX服务?请告诉我"
| 角色 | 动作 | 说明 |
|---|---|---|
| 客户端(如座舱) | 广播Find | "谁有0x0300(车窗控制服务)?请告诉我" |
| 服务端(如车窗ECU) | 单播Offer | "我有,我在192.168.1.100" |
"Find是客户端的'主动寻问'。 等不到Offer,就自己喊一嗓子。"
二、什么时候用Find
黄蓉画了一张场景对比表:
| 场景 | Offer | Find |
|---|---|---|
| 服务端先启动,客户端后启动 | ✅ 客户端能收到 | ❌ 不需要 |
| 客户端先启动,服务端后启动 | ❌ 客户端没收到 | ✅ 客户端主动问 |
| 网络丢包,Offer丢失 | ❌ 客户端没收到 | ✅ 客户端主动问 |
| 客户端想刷新服务列表 | --- | ✅ 主动问一下 |
| 服务端稳定期(3秒才发一次) | 可能要等3秒 | ✅ 立即问,不用等 |
"Find的核心理念:不等了,我自己问。"
三、一个完整的Find报文示例
黄蓉调出一个座舱寻找车窗服务的完整报文(按字段分组):
FF FF | 81 00 | 00 00 00 14 | 12 34 | 00 05 | 01 | 01 | 02 | 00 | 01 | 01 | 00 00 | 00 08 | 03 00 | 00 00 | 00 00 00 00
第一步:SOME/IP头部(12字节)
| 分组 | 值 | 说明 |
|---|---|---|
| Service ID | FF FF |
SD专用固定ID |
| Method ID | 81 00 |
SD专用固定Method ID |
| Length | 00 00 00 14 |
20字节 |
| Client ID | 12 34 |
座舱的ID |
| Session ID | 00 05 |
第5次请求 |
| Message Type | 02 |
NOTIFICATION |
"看到FF FF 81 00,还是SD消息。"
第二步:SD头部(4字节)
| 分组 | 值 | 说明 |
|---|---|---|
| Version | 01 |
SD版本1 |
| Message Type | 01 |
Find Service(注意:Offer是02,Find是01) |
| Reserved | 00 00 |
保留 |
| Entry Count | 00 00 00 01 |
有1个Entry |
第三步:Find Entry
| 分组 | 值 | 说明 |
|---|---|---|
| Entry Type | 00 00 |
Find Service(Offer是00 01) |
| Length | 00 08 |
8字节 |
| Service ID | 03 00 |
要找的车窗控制服务 |
| Instance ID | 00 00 |
0x0000表示"找这个服务的所有实例" |
| TTL | 00 00 00 00 |
Find消息不需要TTL,全0 |
郭靖注意到Instance ID是00 00:"为什么不是00 01(左前窗)?"
黄蓉:"Instance ID=0x0000是通配符,意思是'找这个服务的所有实例'。 座舱不关心是左前还是右前,谁回都行。"
四、服务端收到Find后做什么
黄蓉画了车窗ECU收到Find后的处理流程:
车窗ECU收到Find报文:
│
├── 解析出要找的服务:Service ID=0x0300
│
├── 检查自己有没有这个服务 → 有!
│
├── 单播回复Offer给座舱(不是广播)
│
└── Offer报文内容:
Service ID=0x0300,Instance ID=0x0001
IP=192.168.1.100,Port=30490,TTL=3
"关键区别:Find的响应是单播,不是广播。 谁问的,就单独回给谁,不打扰其他人。"
五、Find vs Offer 对比
黄蓉画了一张对比表:
| 对比项 | Offer | Find |
|---|---|---|
| 谁发起 | 服务端 | 客户端 |
| 触发时机 | 上电后、续约时 | 需要服务时、等不到Offer时 |
| 发送方式 | 广播(告诉所有人) | 广播(问所有人) |
| 响应方式 | 无响应(单向广播) | 单播Offer(谁问回谁) |
| Entry Type | 0x0001 |
0x0000 |
| Instance ID | 具体实例(如0x0001) | 通配符(0x0000)或具体值 |
| TTL | 有效期(如3秒) | 全0(不需要) |
郭靖恍然大悟:"哦~~Offer是'我来了,你们都知道一下',Find是'谁在?过来回我一下'。"
六、Find的典型使用场景
黄蓉画了一个时序图,展示Offer和Find如何配合:
车窗ECU(服务端) 座舱(客户端)
│ │
│ ① 车窗ECU上电,发Offer(广播) │
│ “我会0x0300,我在192.168.1.100” │
│─────────────────────────────────────>│(座舱没收到,因为还没启动)
│ │
│ │ ② 座舱上电
│ │
│ │ ③ 座舱等了一会儿,没收到Offer
│ │
│ ④ 座舱发Find(广播) │
│ “谁有0x0300?” │
│<─────────────────────────────────────│
│ │
│ ⑤ 车窗ECU单播Offer │
│ “我有,我在192.168.1.100” │
│─────────────────────────────────────>│
│ │
│ │ ⑥ 座舱记下服务地址
"Offer + Find 双保险,确保客户端总能找到服务。"
七、黄蓉的小本本
郭靖翻开她的笔记本,上面写着:
Find Service核心要点:
1. 客户端主动问:等不到Offer,就自己喊"谁有XX服务?"
2. 什么时候用:客户端启动晚、网络丢包、想刷新服务列表
3. Entry Type :
0x0000(Find Service)4. Instance ID通配符 :
0x0000表示"找所有实例"5. 响应方式 :服务端单播Offer给询问的客户端
6. 与Offer配合:Offer + Find = 双保险
一句口诀:主动通知未收好,自己寻问自己找
写在最后
郭靖合上笔记本:"Find是客户端主动问'谁会啥'。服务端收到后,单播回复Offer。Offer和Find配合,客户端总能找到服务,不管谁先启动。"
黄蓉咬了口糖葫芦:"知道了服务端怎么喊、客户端怎么问。那如果想收通知(Event/Field Notifier),怎么订阅?"
郭靖摇头。
"下篇预告:想收通知要订阅,EventGroup来帮忙------Subscribe详解。"
打完收工,886。