文章中,我们了解了一条完整的SOME/IP报文应该长什么样子,但这显然是不够的,至少还有以下这几个问题并没有得到明确的解决:
-
Client如何发现服务
-
当服务不可用时,如何通知Client
-
Client如何订阅事件
这些就是SOME/IP-SD要做的事情了。SOME/IP-SD也是基于SOME/IP的报文,用来实现服务发现和事件订阅机制。SOME/IP-SD消息通过UDP进行传输,报文格式如下图所示:
Flags=重新启动标志+单播标志+显示初始数据控制标志,如下图所示:
服务重新启动后,所有消息的Reboot Flag须置为1,直到Session ID重新从1开始计数,之后的Reboot Flag须置为0。
Entries Array,Entry可以理解为“入口”,包含了服务实例以及需要订阅的事件组的信息,分为Service和Eventgroup两种类型,一个SD报文可能包含多个Entry,每个Entry大小都是16个字节,一个Entry可能包含0-2个Option。下图为一个完整的SD报文示例:
Service Entry 用于服务发现:
Type值 | 名称 |
---|
0x00 | FindService |
0x01 | OfferService |
StopOfferService |
-
Index 1st options:Option1排在Array里第几个
-
Index 2nd options:Option2排在Array里第几个
-
# of opt 1:Option1的数目
-
# of opt 2:Option2的数目
-
Service ID:Entry关于哪个服务
-
Instance ID:Entry关于服务的哪个实例,0xFFFF表示全部实例
-
Major Version:服务的主版本号
-
TTL:“入口”的生命周期,单位为秒,我理解为发现服务时的搜索时间,提供服务时的有效时间
-
Minor Version:服务的次版本号
服务发现,说白了,就是想办法让服务消费者能够找到服务提供者。打个比方,想象你在一个有很多人的广场上找一个会唱歌的人,很显然有两种情况:1. 你认识这个人,提前说好了,他站在某个地方等你,而你知道那个地方的位置,那你肯定很容易就找到他了,这就是静态配置;2. 你并不认识这个人,存在一个中间人,你告诉中间人你想找一个会唱歌的,而那个人也会告诉中间人我是会唱歌的,我站在广场的哪个位置,然后中间人把位置给你,你就可以找到他了,这就是动态发现,而SOME/IP-SD就是那个中间人。
Eventgroup Entry 用于事件订阅:
Type值 | 名称 |
---|
0x06 | Subscribe |
StopSubscribeEventgroup |
0x07 | SubscribeAck |
SubscribeEventgroupNack |
下面的示例,说明了一个Client发现服务和订阅事件组的过程:
Options Array,Option可以理解为选项参数,Type=0x01时,用于传输Entry的附加信息,比如服务名等等:
Type=0x04时,用于传输IPv4相关的参数,比如服务的IP地址、TCP还是UDP、端口号:
从下图可知,对于不同的消息,要配置的选项类型也不一样,甚至不需要配置,其他几种选项的具体内容不一一列举了,用到了查下官方文档就行了,关注公众号,回复“SOMEIP协议”,即可获得相关文档~
到这里,SOME/IP算介绍完了。是不是觉得如果要自己实现SOME/IP全部的协议,还是有点复杂的,目前GENIVI的vsomeip开源库已经实现了SOME/IP协议栈,所以通常并不用再去造轮子。换言之,我们完全可以基于vsomeip开发SOME/IP应用程序,不用关心报文长什么样,也不用关心服务发现和事件订阅的细节,拿到手已经是Payload了,如果再用上GENIVI的CommonAPI,IDL一写,一条命令下去,代码自动生成了,Payload都用不着解析了,这样就实现了真正的RPC,是不是有点感兴趣了呢,那就继续关注我吧
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)