Android车机STR启动后someip出现的tcp握手失败

发布于:2024-08-11 ⋅ 阅读:(296) ⋅ 点赞:(0)

        项目中遇到一个someip的问题,每次车机的Android系统从STR恢复后,其他域上的操作系统中的someip客户端无法连接上Android系统中的someip客户端,无法获取get到发布的someip服务,该someipi服务使用的reliable的通信(TCP)。

        然后,通过抓包发现从STR回复后,在其他域上抓包可以抓到Android系统上someip服务发出的offer报文,但是其他域上的someip客户端发送的TCP SYNC包有出现重传的情况(有TCP Retransmittion记录),并且没有抓到Android系统上的TCP SYNC包,也就是握手失败。

        最后发现是因为下面两个原因:

        1. 其他域上的someip客户端在STR回复后会进行进程重启

        2. 其他域上的someip客户端使用的someip配置中,"services"中的reliable配置使用了固定端口

        配置的情况如下:


someip服务端使用的vsomeip.json中service的配置
"services" :
    [
        {
            "service" : "0x1234",
            "instance" : "0x5678",
            "protocol" :"someip",
            "unicast" : "10.0.2.15",
            "reliable" : [
                "port" : "30490",
                "enable-magic-cookies" : "true",
            ],
            ......

someip客户端使用的vsomeip.json中client的配置
"clients" : 
    [
        {
            "service" : "0x1234",
            "instance" : "0x5678",
            "reliable" : [
                "port" : "30490",
                "enable-magic-cookies" : "true",
            ],

这就导致在时序上可能发生下面这种情况 :

1. 车机启动

2. Android侧启动someip服务端,服务0x1234使用TCP通信,创建服务端TCP socket,绑定30490端口进行监听。

3. QNX的someip客户端启动,获取Andriod侧的0x1234服务,创建TCP socket,绑定30490端口,然后使用该socket连接Android创建的TCP socket(端口30490)

4. TCP连接建立,Android侧记录了和QNX的someip客户端的连接(远端端口30490)

5. 车机进入STR

6. 车机退出STR

7. QNX退出STR,重启someip客户端进程

8. Android侧的someip服务端进程继续运行(未重启),并且维护了和远端someip客户端建立的TCP连接(Android IP: 30490 -> QNX IP: 30490)  // 这里的这个TCP连接是STR之前建立的

9. QNX侧的someip客户端进程获取0x1234服务,重复步骤3, 该部出错,TCP连接没有建立成功

        问题就在于退出前,QNX的someip客户端没有断开和someip服务端的TCP连接(没有注销获取到的SERVICE),因此,没有收到FIN包的Andriod侧依然认为该TCP连接是有效的,连接的远端端口是30490。

        然后退出STR后,QNX侧先启动,然后重启了someip客户端进程,此时,someip客户端发送的FIN包不一定被Android侧的someip服务端收到(因为Android侧还在STR中没有退出来)。

        接着Android从STR回复,之前的someip服务端进行继续运行(进程号都不变,还是STR之前的进程), QNX侧重启后的someip客户端进程收到了Android侧发送的offer报文,希望获取该service,并且建立TCP连接,因此绑定了QNX的30490端口来连接Android侧的someip服务端socket,因为Android侧还为之前QNX端的TCP socket(30490端口)还是有效的,因此对这次新的TCP握手请求没有相应(因为SYNC包中的远端端口还是30490)。

        后续的解决方法就是在配置文件中不设置service的reliable端口,让协议栈创建socket时自己动态获取。