综述:

一、车载以太网消息格式

如上图所示DOIP消息分为诊断请求、ack、以及应答,其中诊断请求payload固定为0x8001,ack和nack为payload为0x8002或者0x8003,诊断响应payload固定为0x8001

二、粘包出现原因

1.以太网诊断同can诊断类似,也有功能寻址和物理寻址之分,其中10服务、28服务、11服务、85服务、3E服务,在ota过程中一般由功能寻址发送

2.升级过程中为保持诊断设备在线,诊断仪会单独起一个线程以功能寻址定时2/4s 发送3E请求,此时即可能出现以下情况:
a.被测设备接收数据出现粘包,被测设备接收诊断请求出现3E请求与其它诊断服务请求粘包

b.诊断设备接收到返回数据粘包,其中包含ack接受到3E服务响应粘包,RX接收到3E服务响应/0x78等待响应粘包

三、粘包出现处理办法-拆包

1.发送3E请求时SPRMB禁止肯定响应位置1,避免诊断仪接收到数据3E请求应答与其它诊断服务响应粘包

2.诊断可能出现的粘包情况,需进行拆包处理,根据DOIP固定数据格式特点拆包

sticy_flag=0

def Unpacking(data):
    global sticy_flag
    sticy_flag = 0   #拆包前标志位清0
    a=data
    common.writelog( f"*****拆包前数据****** {a} ")
    #RX拆包

    if a.count('02FD8001')==2:
        print('RX出现粘包')
        #print(a[8:16])
        #print(a[28:30])
        if a[8:16]=='00000007' and a[28:30]=='78':
            a=a[30:]
            #print(a)
        elif a[8:16] == '00000006' and a[26:28] == '3E':
            a = a[28:]
            # print(a)
        else:
            position_last=a.rfind('02FD8001')
            #print(position_last)
            a=a[0:position_last]
            #print(a)
    if '02FD8002' in a and  '02FD8001' in a :
        sticy_flag=1
        print("ACK+RX粘包")

        a=a[a.rfind('02FD8001'):]

    else:
        #print('无需拆包')
        pass
    #ack拆包
    if a.count('02FD8002') == 2:
        print('ACK出现粘包')
        if a[8:16]=='00000006' and a[26:28]=='3E':
            a=a[28:]
        else:
            position_last = a.rfind('02FD8002')
            a = a[0:position_last]
            # print(position_last)
            # print(a)
    if a.count('02FD8002') >2:
        while True:
            if a[8:16]=='00000006' and a[26:28]=='3E':
                a=a[28:]
            else:
                break
    if a:
        pass
    else:
        print("未收到有效数据!!!")
    return a

我这里采用的是自己写的测试脚本,拆包方式如上,仅供参考!

更多推荐