写在开篇·蓉儿接着挖坑
上回说到,郭靖搞清楚了Service ID是服务的“门派番号”,车窗服务是0x0300。
郭靖合上笔记本,信心满满:“蓉儿,Service ID我搞明白了!车窗服务就是0x0300。”
黄蓉咬了口糖葫芦:“那好,我问你——车上四个车窗,都用同一个Service ID0x0300,那你想控制左前车窗升窗,报文发出去,怎么让左前车窗知道是找它,而不是右前、左后、右后?”
郭靖一愣:“这……报文头里也没位置字段啊?”
“今天就用四个车窗当例子,把Instance ID这一个知识点讲透。读完这篇,你就知道同一服务如何区分不同‘分身’。”
附:SOME/IP报文结构速查表
💡小贴士:别忘了报文头结构,Instance ID不在报文头里,藏在Payload中。
| 字节偏移 | 字段 | 长度 | 说明 |
|---|---|---|---|
| 0-1 | Service ID | 16位 | 服务的唯一标识(车窗=0x0300) |
| 2-3 | Method ID / Event ID | 16位 | 具体的方法或事件ID(升窗=0x0001) |
| 4-7 | Length | 32位 | 从Request ID开始到报文结束的总长度 |
| 8-9 | Client ID | 16位 | 客户端标识 |
| 10-11 | Session ID | 16位 | 会话标识,用于匹配请求和响应 |
| 12 | Protocol Version | 8位 | 协议版本号,当前固定为0x01 |
| 13 | Interface Version | 8位 | 服务接口的版本号 |
| 14 | Message Type | 8位 | 消息类型(0x00=REQUEST) |
| 15 | Return Code | 8位 | 返回码(0x00=E_OK) |
| 16... | Payload | 可变 | Instance ID就藏在这里的头几个字节 |
一、Instance ID是什么
Instance ID = 16位数字,是同一服务下不同“分身”的标识。
车窗服务的例子:
| 车窗位置 | Service ID(相同) | Instance ID(不同) |
|---|---|---|
| 左前车窗 | 0x0300 | 0x0001 |
| 右前车窗 | 0x0300 | 0x0002 |
| 左后车窗 | 0x0300 | 0x0003 |
| 右后车窗 | 0x0300 | 0x0004 |
“Service ID都一样,Instance ID不一样。就像丐帮只有一个番号,但洛阳分舵和襄阳分舵,编号不同。”
二、Instance ID藏在哪儿
郭靖追问:“那Instance ID到底放在报文的哪个位置?报文头里可没有这个字段。”
黄蓉画了一个完整的车窗升窗报文结构:
| 报文部分 | 内容 | 说明 |
|---|---|---|
| 报文头(12字节) | 03 00 00 01 00 00 00 08 12 34 00 01 01 01 00 00 | Service ID=0x0300,Method ID=0x0001 |
| Payload(载荷) | 00 0101 00 | 前2字节00 01就是Instance ID=0x0001(左前) |
“看清楚了吗?Instance ID不在报文头里,藏在载荷的头两个字节。接收方先看Service ID找到车窗服务,再看载荷里的Instance ID知道是哪个窗。”
三、一个真实的服务定义表(带Instance ID)
黄蓉从电脑里调出完整的车窗服务定义表:
| Service ID | Instance ID | Method/Event ID | 类型 | 名称 | 说明 |
|---|---|---|---|---|---|
0x0300 | 0x0001 | 0x0001 | Method | Window.LF.Raise | 左前车窗升窗 |
0x0300 | 0x0001 | 0x8001 | Event | Window.LF.PositionEvent | 左前车窗位置变化事件 |
0x0300 | 0x0002 | 0x0001 | Method | Window.RF.Raise | 右前车窗升窗 |
0x0300 | 0x0002 | 0x8001 | Event | Window.RF.PositionEvent | 右前车窗位置变化事件 |
0x0300 | 0x0003 | 0x0001 | Method | Window.LR.Raise | 左后车窗升窗 |
0x0300 | 0x0004 | 0x0001 | Method | Window.RR.Raise | 右后车窗升窗 |
郭靖盯着表格问:
“左前和右前,Service ID都是
0x0300,Method ID都是0x0001,全靠Instance ID区分。那这个Instance ID是谁定的?能不能随便写?”
黄蓉:“跟Service ID一样,由整车架构师统一分配。Instance ID在同一个Service ID下必须唯一,不能重复。”
四、Instance ID的其他“藏身”方式
郭靖又问:
“我一直以为Instance ID只能放在载荷里,有没有其他方式?”
黄蓉列举了三种常见方式:
| 方式 | 说明 | 车窗例子 | 优缺点 |
|---|---|---|---|
| 载荷中携带 | 报文头只有Service ID,载荷第一个字段是Instance ID | 左前升窗:载荷头00 01 | 简单直接,不占额外资源 |
| SD阶段区分 | 每个Instance单独提供服务,用不同IP/端口 | 左前在192.168.1.101,右前在192.168.1.102 | 报文头干净,但需要更多IP |
| TCP连接区分 | 每个Instance单独建立一个TCP连接 | 左前用一个TCP连接,右前用另一个 | 连接管理复杂 |
五、总结:Service ID + Instance ID + Method ID 三件套
黄蓉画了一张完整的关系图:
| 层级 | 车窗例子 | 作用 |
|---|---|---|
| Service ID | 0x0300 | 找到车窗服务(找到门派) |
| Instance ID | 0x0001(左前) | 找到具体哪个车窗(找到分舵) |
| Method ID | 0x0001(升窗) | 执行什么操作(找到招式) |
“三件套凑齐,才能精准调用:Service ID找大门,Instance ID找房间,Method ID找具体操作。”
六、黄蓉的小本本
郭靖翻开她的笔记本,上面写着:
Instance ID= 同一服务下不同“分身”的标识,由整车架构师统一分配
四个车窗:Service ID相同=
0x0300,Instance ID不同=0x0001-0x0004Instance ID不在报文头里,藏在载荷的头两个字节(或从SD阶段/连接区分)
三件套:Service ID(什么服务)+ Instance ID(第几个)+ Method ID(什么操作)
写在最后
郭靖合上笔记本:“Service ID找到车窗服务,Instance ID找到左前窗,Method ID执行升窗。三件套凑齐,调用才不会乱。”
黄蓉咬了口糖葫芦:“那你知道了Service ID和Instance ID,知道Method和Event有什么区别吗?为什么有的操作是你问他答,有的是他自己说?”
郭靖摇头。
“靖哥哥,升窗一问一答,Event自己说话——Method vs Event。” 下次培训啦。
打完收工,886。