SOME/IP--协议英文原文讲解5

news/2025/2/10 11:22:57/

前言
SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块:

1. SOME/IP协议讲解

2. SOME/IP-SD协议讲解

3. python/C++举例调试讲解 


这一章节是按照规范文档顺序讲解的。按内容 这章节应该排在 string/arry数据类型讲解完 再讲 才好理解。读者可直接先阅读 后面string/arry内容后再回过来看这一节。


4.1.4.3 Structured Datatypes and Arguments with Identifier and optional members (’TLV’)
To achieve enhanced forward and backward compatibility, an additional Data ID can
be added in front of struct members or method arguments. The receiver then can
skip unknown members/arguments, i.e. where the Data ID is unknown. New members/arguments can be added at arbitrary positions when Data IDs are transferred in the
serialized byte stream.
Moreover, the usage of Data IDs allows describing structs and methods with optional
members/arguments. Whether a member/argument is optional or not, is defined in the
data definition.
Whether an optional member/argument is actually present in the struct/method or not,
must be determined during runtime. How this is realized depends on the used programming
language or software platform (e.g. using a special available flag, using a
special method, using pointers which might be null, ...).

给结构体每个成员前加个数据ID 用于标识当前methed/notify/struct每个参数成员的唯一性。这样的一个好处就是就是可以向前、后兼容。另一个好处就是同一个method/notify的参数列表(也可以理解成结构体成员,只是对连续多个数据组织方式的一种描述)可以做配置项--打开或关闭,这个要在运行时体现,需要在代码中配置好。比如:同一个method, 根据不同的入参请求 返回不同的参数表。后面说的dataID 也可以称为Tag.

发送端给需要发送的成员的前添加ID,接收端就可以根据ID判断 是哪个成员参数,无法识别的就跳过。这样成员的顺序就没强制要求。

注意:上面说的参数列表是notify/method的所有参数。TLV-struct如果是被嵌套在另一个非TLV的struct中,那TLV-struct就是notify/method就是参数的一部分。SOME/IP TLV的用法和Protobuf协议中TLV一样,可以做参考。

### **TLV的缺点:**

1. **数据冗余:**
   - 每个字段都有Tag和Length,会增加传输的数据量。

2. **实现复杂度提升:**
   - 需要为TLV的序列化和反序列化设计专门的逻辑。
   - 特别是Tag和Length的编码需要一致性,并需要在传输前进行规划。

---

### **总结:TLV的必要性**

尽管直接传输结构体在简单系统中更高效,但在复杂通信场景(如AUTOSAR车载系统)中,使用TLV提供了以下关键优势:
- **前向兼容性**:支持较新版本的字段。
- **后向兼容性**:跳过旧版本不支持的字段。
- **动态扩展性**:支持可选字段和未来扩展。

[PRS_SOMEIP_00201]
Upstream requirements: RS_SOMEIP_00050
A Data ID shall be unique within the direct members of a struct or arguments of a
method. 同一个method/notify/struct的 数据成员ID 要唯一,否则不需要唯一。
Note:
Please note that a Data ID does not need to be unique across different structs or
methods. 
Note:
Please note that neither the AUTOSAR Methodology nor AUTOSAR CP RTE, nor
AUTOSAR AP ara::com support the definition or usage of optional method arguments
at the time being. --- 不过现在的AUTOSAR版本不支持可变参数列表的功能

[PRS_SOMEIP_00230]
Upstream requirements: RS_SOMEIP_00050
A Data ID shall be defined either for all members of the same hierarchical level of a
struct or for none of them. -- 同一层次级别的所有参数成员 要么都有ID标识 要么都没有。

[PRS_SOMEIP_00231]
Upstream requirements: RS_SOMEIP_00050
A Data ID shall be defined either for all arguments of a method or for none of them.
In addition to the Data ID, a wire type encodes the datatype of the following member.
Data ID and wire type are encoded in a so-called tag. dataID中有专门几个位是wire-type,用来表示后面携带数据的数据类型,用以反序列化时知道后面数据类型的长度。
[PRS_SOMEIP_00202]
Upstream requirements: RS_SOMEIP_00050
The length of a tag shall be two bytes. tag ID 占用两个字节

 WireType是第一个字节的4-6位,真正的DataID占12位。图中后面跟的长度域加个框表示可能有这个长度域--由wrie type决定。

[PRS_SOMEIP_00204]
Upstream requirements: RS_SOMEIP_00050
The lower significant part of the Data ID of the member shall be encoded in bits 7-0
of the second byte of the tag. The higher significant part of the Data ID of the member
shall be encoded in bits 3-0 of the first byte.
Example:
The Data ID of the member is 0x04F2. Then bits 3-0 of the first byte are set to 0x4.
The second byte is set to 0xF2.

举例说明了 DataID怎么编码。

WireType对应的类型 解释。--后面详解

Note: wire type 4 ensures the compatibility with the current approach where the size of length fields is statically configured. This approach has the drawback that changing the size of the length field during evolution of interfaces is always incompatible. Thus, wire types 5, 6 and 7 allow to encode the size of the used length field in the transferred byte stream. A serializer may use this, if the statically configured size of the length field is not sufficient to hold the current size of the data struct.

 类型4-7 对应的数据类型是Arry/struct/string中的一种,类型4的长度字段是客户自定,定好后编程、通信双方按照这个配置来序列化、反序列化。类型5-7则对应添加1、2、4字节的长度段。

[PRS_SOMEIP_00206]
Upstream requirements: RS_SOMEIP_00050
If the wire type is set to 5, 6 or 7, the size of the length field defined in the data
definition shall be ignored and the size of the length field shall be selected according
to the wire type.
If a Data ID is configured for a member of a struct/argument of a method, a tag shall
be inserted in the serialized byte stream.
Note:
regarding the existence of Data IDs, refer to [PRS_SOMEIP_00230] and
[PRS_SOMEIP_00231].

wireType 5-7 因为添加了长度字段,则需要忽略后面数据类型中前面的长度字段。如果是struct类型,前面有客户指定添加的长度段(通信双方都应知道)需要忽略,但是struct成员中的类型可能前面有长度字段 ,则不能忽略。

有DataID,必然有Tag。

[PRS_SOMEIP_00212]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
If the datatype of the serialized member/argument is a basic datatype (wire types 0-3)
and a Data ID is configured, the tag shall be inserted directly in front of the member/argument.
No length field shall be inserted into the serialized stream. wireType是0-3则数据前不需要长度段。
[PRS_SOMEIP_00213]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
If the datatype of the serialized member/argument is not a basic datatype (wire type
4-7) and a Data ID is configured, the tag shall be inserted in front of the length field. wireType是4-7则数据前必需要长度段。tag字段必须要在长度段之前。
[PRS_SOMEIP_00214]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
If the datatype of the serialized member/argument is not a basic datatype and a Data
ID is configured, a length field shall always be inserted in front of the member/argument.
Rationale:
The length field is required to skip unknown members/arguments during deserialization.长度段的作用是在反序列化时跳过未知的数据成员(dataID)。
[PRS_SOMEIP_00221]
Upstream requirements: RS_SOMEIP_00040, RS_SOMEIP_00050
The length field shall always contain the length up to the next tag of the struct.长度字段描述的长度必须要包含截至到下一个tag字段之前。

[PRS_SOMEIP_00208]
Upstream requirements: RS_SOMEIP_00040, RS_SOMEIP_00050
If the members/arguments itself are of type struct, there shall be exactly one length
field. The length field is added according to requirements [PRS_SOMEIP_00079] and
[PRS_SOMEIP_00370]. 如果TLV数据成员本身就是struct类型,则前面必须要加上长度字段。(前面章节有讲:如果非TLV的数据则struct类型前 的长度字段是可配置的,可以有 也可以没有 需要客户指定)。

[PRS_SOMEIP_00225]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type dynamic length string, there shall
be exactly one length field. The length field is added according to requirements 
[PRS_SOMEIP_00089], [PRS_SOMEIP_00090], [PRS_SOMEIP_00093],
[PRS_SOMEIP_00094] and [PRS_SOMEIP_00095]. 如果TLV数据成员是动态长度string类型,则前面必须要加上一个长度字段。(后面章节讲:正常非TLV 动态长度string类型也要有,不过这里明确指出 意思是不能省略这个长度段)。

[PRS_SOMEIP_00224]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type fixed length string, there shall be exactly
one length field corresponding to dynamic length strings.如果TLV数据成员是定长string类型,则前面必须要加上一个长度字段。
Note:
when serialized without tag, fixed length strings do not have a length field. For the
serialization with tag, a length field is also required for fixed length strings in the same
way as for dynamic length strings.(后面章节讲:正常非TLV 定string类型是没有的)但是TLV的类型需要加上这个长度字段 (和动态长度string一样)。
[PRS_SOMEIP_00227]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type dynamic length array, there shall be
exactly one length field. The length field is added according to requirements
[PRS_SOMEIP_00376], [PRS_SOMEIP_00107], [PRS_SOMEIP_00377] with a size
of 8, 16 or 32 bit.
[PRS_SOMEIP_00226]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type fixed length array, there shall be exactly
one length field corresponding to dynamic length arrays.

不管是定长、动态Arry类型 如果是TLV类型 则前面必须要加上长度字段,具体添加规则参考需求:[PRS_SOMEIP_00376], [PRS_SOMEIP_00107], [PRS_SOMEIP_00377]

[PRS_SOMEIP_00228]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type union, there shall be exactly one length
field. The length field is added according to requirements [PRS_SOMEIP_00119],
[PRS_SOMEIP_00121] with a size of 8,16 or 32 bit.
[PRS_SOMEIP_00229]
Upstream requirements: RS_SOMEIP_00050
If the members/arguments itself are of type union, the length field shall cover the size
of the type selector field, data and padding bytes.
Note:
For the serialization without tags, the length field of unions does not cover the type
selector field (see [PRS_SOMEIP_00126]). For the serialization with tags, it is required
that the complete content of the serialized union is covered by the length field.

联合体类型 需要在前面加上长度字段,添加方法参见:[PRS_SOMEIP_00119],
[PRS_SOMEIP_00121],但不同的是,TLV类型联合体前的长度字段描述的长度必须涵盖联合体的最大长度(序列化时,实际长度小于最大长度,后面添加空白字节)(注意:正常非TLV的联合体是不用覆盖最大长度的)。

[PRS_SOMEIP_00210]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
A member of a non-extensible (standard) struct which is of type extensible struct, shall
be serialized according to the requirements for extensible structs.
[PRS_SOMEIP_00211]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
A member of an extensible struct which is of type non-extensible (standard) struct,
shall be serialized according to the requirements for standard structs.

当一个非可扩展(标准)结构的成员是一个可扩展结构的类型时,这个成员应当按照可扩展结构的序列化要求来进行序列化。当一个可扩展结构的成员是一个非可扩展(标准)结构的类型时,这个成员应当按照非可扩展(标准)结构的序列化要求来进行序列化。

non-extensible (standard) struct:非TLV struct

extensible struct:TLV 带tag的struct

具体的意思是:TLVstrtuct嵌套个 非TLVstruct成员则成员序列化时这个非TLVstruct成员前面要加上tag/dataID。非TLVstrtuct嵌套个 TLVstruct成员则成员序列化时这个TLVstruct成员前不用加tag/dataID。


[PRS_SOMEIP_00222]
Upstream requirements: RS_SOMEIP_00029, RS_SOMEIP_00050
The alignment of variable length data according to [PRS_SOMEIP_00611] shall always be 8 bit.
Rationale:
When alignment greater 8 bits is used, the serializer may add padding bytes after
variable length data. The padding bytes are not covered by the length field. If the
receiver does not know the Data ID of the member, it also does not know that it is
variable length data and that there might be padding bytes.

对于可变长度的成员内存对齐采用1字节对齐。

理由:

  • 避免填充字节问题:当使用大于8位的对齐方式时,序列化器可能会在变长数据之后添加填充字节以满足对齐要求。这些填充字节不被长度字段所涵盖,因此接收方在解析数据时可能会遇到困难。
  • 接收方信息不足:如果接收方不知道成员的数据ID,它就无法确定该成员是否是变长数据,也无法预测是否存在填充字节。这可能导致数据解析错误或数据丢失。
  • 确保数据一致性:通过规定8位对齐,可以确保发送方和接收方在数据对齐方式上达成一致,从而避免由于对齐不一致而导致的数据解析问题。

[PRS_SOMEIP_00241]
Upstream requirements: RS_SOMEIP_00050
If TLV is used the size of the length field for arrays, structs, unions and strings shall
be greater than 0.
Rationale:
The TLV serialization requires the usage of length fields. When wire type 4 is used, the
length field size must be statically configured. When wire types 5-7 (dynamic length
field size) are used, the static configuration of the length field size must also be present
since not all length fields are preceded by a tag, e.g. structs contained in an array or
the top-level struct contained in a SOME/IP event. Not using length fields here would
result in ambiguities.
[PRS_SOMEIP_00242]
Upstream requirements: RS_SOMEIP_00050
The configured size of the length field for arrays, structs, unions and strings shall be
identical.
Rationale:
In case of an unknown member or argument, the deserializer cannot determine the
actual datatype of the member/argument when wire type 4 is used.

该要求指出,在使用类型-长度-值(TLV)序列化时,数组、结构体、联合体以及字符串的长度字段大小必须大于0。

理由:
  • TLV序列化的需求:TLV序列化方法要求使用长度字段来明确每个值(Value)部分的大小。这是为了确保在解析序列化数据时能够准确地恢复原始数据结构。
  • 长度字段的重要性:当使用特定的线类型(wire type)时(例如线类型4),长度字段的大小需要静态配置。即使使用动态长度字段大小的线类型(如5-7),也需要存在静态配置的长度字段大小,因为并非所有长度字段之前都有标签。例如,数组中包含的结构体或SOME/IP事件中包含的顶级结构体就没有前置标签。如果不使用长度字段,将会导致解析时的歧义。

[PRS_SOMEIP_00243]
Upstream requirements: RS_SOMEIP_00050
The size of the length field shall be configured for the top-level struct or method request/response. 
All arrays, unions, structs and strings used within a struct or all arguments within a method shall
inherit the size of the length field from the top-level definition.
Rationale:
In case of an unknown member or argument, the deserializer needs to know the size of
the length field when wire type 4 is used. The easiest way is that the size of the length
field is then only defined at the top-level element.

要求内容

  • 长度字段的大小应为顶级结构体或方法请求/响应配置。
  • 在结构体内部使用的所有数组、联合体、结构体和字符串,或者在方法内部使用的所有参数,应当从顶级定义继承长度字段的大小。

理由

  • 当使用线类型4(wire type 4,在Protocol Buffers中表示长度分隔的字段)时,如果遇到未知成员或参数,反序列化器需要知道长度字段的大小。
  • 最简单的方式是只在顶级元素处定义长度字段的大小,这样可以在整个数据结构中保持一致,并简化处理逻辑。

[PRS_SOMEIP_00244]
Upstream requirements: RS_SOMEIP_00050
Overriding the size of the length field at a subordinate array, union, struct or string or
at an individual method argument shall not be allowed.
[PRS_SOMEIP_00216]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
The serializer shall not include optional members/arguments in the serialized byte
stream if they are marked as not available.
[PRS_SOMEIP_00220]
Upstream requirements: RS_SOMEIP_00028, RS_SOMEIP_00050
If the serialization with tags will be introduced for an existing service interface where
tags have not been used, the major interface version shall be incremented and used to
indicate this.
Note:
The receiver only handles received messages that match all configured values of Message ID, 
Protocol Version, Interface Version and Message-Type (see[PRS_SOMEIP_00195]).

PRS_SOMEIP_00244

上游需求:RS_SOMEIP_00050

要求内容:
不允许在子数组、联合体、结构体或字符串或单个方法参数中覆盖长度字段的大小。

解释:
为了确保数据的一致性和简化处理逻辑,SOME/IP协议要求长度字段的大小在顶级结构体或方法请求/响应中定义后,其内部的所有数据结构或参数必须继承这一大小配置。不允许在下级元素中覆盖这一设置,以避免可能的解析错误或数据不一致。

PRS_SOMEIP_00216

上游需求:RS_SOMEIP_00028, RS_SOMEIP_00050

要求内容:
如果可选成员/参数被标记为不可用,则序列化器不应将其包含在序列化字节流中。

解释:
在SOME/IP协议中,可选成员/参数的存在与否可以通过特定的标记来指示。如果某个可选成员/参数在当前的消息或请求中不可用,那么序列化器在构建要发送的字节流时应该忽略它,以节省带宽和简化处理。

PRS_SOMEIP_00220

上游需求:RS_SOMEIP_00028, RS_SOMEIP_00050**

要求内容:
如果要在未使用标签的现有服务接口中引入带标签的序列化,则应增加主要接口版本并使用它来指示这一点。

解释:
在SOME/IP协议中,服务接口的版本控制对于确保向后兼容性和处理接口更改至关重要。如果要在现有服务接口中引入新的序列化机制(例如,使用标签来区分不同的可选成员/参数),则必须增加主要接口版本以反映这一更改。这样做可以确保接收方能够识别并正确处理新版本的消息,同时仍然能够处理旧版本的消息(如果它们仍然被发送)。

注意:
接收方只处理与配置的消息ID、协议版本、接口版本和消息类型(见[PRS_SOMEIP_00195])完全匹配的消息。这意味着,如果发送方发送了一个与接收方期望的版本或类型不匹配的消息,接收方可能会拒绝处理该消息或返回错误。

这些要求共同确保了SOME/IP协议中的消息能够以一种可预测和一致的方式被序列化和反序列化,从而支持可靠的服务间通信。

 

 

4.6例子 的入参是在 请求包中携带那三个参数a b c,  出参d e是在响应报文中携带。并不是在同一条报文中。 


https://github.com/0voice


http://www.ppmy.cn/news/1570850.html

相关文章

ORB-SLAM2源码学习:Tracking.cc:GrabImageStereo、GrabImageRGBD、GrabImageMonocular处理图像

前言 该部分函数在Tracking.cc源文件中定义,用于处理图像。 1.函数作用: 1.GrabImageStereo 函数的主要作用是处理输入的双目图像(左视图和右视图),进行必要的预处理(颜色转换),创…

react使用if判断

1、第一种 function Dade(req:any){console.log(req)if(req.data.id 1){return <span>66666</span>}return <span style{{color:"red"}}>8888</span>}2、使用 {win.map((req,index) > ( <> <Dade data{req}/>{req.id 1 ?…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之上传头像和新增收货地址

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【Spring篇】【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f680;1.上传头像 -持久…

Leetcode 3449. Maximize the Minimum Game Score

Leetcode 3449. Maximize the Minimum Game Score 1. 解题思路2. 代码实现 题目链接&#xff1a;3449. Maximize the Minimum Game Score 1. 解题思路 这一题思路上就是一个二分法&#xff0c;尝试各个score&#xff0c;看看是否可以满足在给定的m次操作限制下&#xff0c;使…

2025年终总结

文章目录 前言2024年回顾1月2月4月5月6月7月8月10月12月 2025年 回顾1月2月 2025年期望 前言 最近因为一些原因&#xff0c;暂停了博客的书写。但是毕竟到年底了&#xff0c;还是简单作个总结好了。 2024年回顾 1月 回家之后。我堂哥找我聊天&#xff0c;说要一起开网店&am…

如何使用deepseek开发一个翻译API

什么是deepseek Deepseek 是一个基于人工智能技术的自然语言处理平台&#xff0c;提供了多种语言处理能力&#xff0c;包括文本翻译、语义分析、情感分析等。它通过深度学习模型和大规模语料库训练&#xff0c;能够实现高质量的文本翻译和多语言理解。Deepseek 的核心优势在于…

Ranger 2.1.0 Admin安装

个人博客地址&#xff1a;Ranger 2.1.0 Admin安装 | 一张假钞的真实世界 Creating MySQL user ranger2 failed 2021-07-01 18:44:53,480 [E] Creating MySQL user ranger2 failed.. 2021-07-01 18:44:53,496 [E] DB schema setup failed! Please contact Administrator. 原…

leetcode_深度搜索和广度搜索 101. 对称二叉树

101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称思路: 1.判断根节点的左右子树是否为空, 若都为空则返回True2.根节点的左右子树其中之一为空或子树的根节点的值不同则返回False3.分别判断根节点左右子树是否相同, 判断时, 左边子树的左节点要对应…