Python模拟服务端或客户端发送SOME/IP消息
1 说明
主要介绍如何使用Python+scapy模块进行SOME/IP以及SOME/IP-SD消息的发送和解析;关于SOME/IP-SD协议的介绍可以查看我的另一篇文章:SOME/IP服务发现协议说明-SD,以及关于SOME/IP协议的介绍可以查看文章:SOME/IP协议说明
2 依赖
- Python
- 版本:3.8(本文章使用Python3.8版本编写的示例代码,实际Python3应该都能兼容,但是没有试过所有的版本)
- scapy
3 服务端
3.1 导包
from scapy.all import *
from scapy.contrib.automotive.someip import *
from scapy.layers.l2 import Ether
from scapy.layers.inet import IP, UDP, TCP
import time
注意:在scapy的模块 scapy.all
中导入了一个交互式的模块 from scapy.autorun import *
,该模块会导致无法打包;如果你需要使用Pyinstaller或其他工具将编写好的脚本打包成EXE之后再执行的话,需要自己处理一下该模块的代码,或者可以直接屏蔽(# from scapy.autorun import *
)该导入(如果不需要使用交互式功能的话);
3.2 参数定义
定义协议需要使用的一些参数,如网卡名称、MAC地址、IP地址、端口号等;
# 注意以下参数需要根据自己的实际情况配置,否则可能无法通信成功
NETWORK_ADAPTER = "Intel(R) Wi-Fi 6 AX201 160MHz" # 定义要使用的网卡
LOCAL_MAC = "01:02:03:04:05:06" # 定义网卡对应的MAC地址
LOCAL_IP = "127.0.0.1" # 定义网卡对应的IP地址(注意此处最好设置为固定的IP地址)
BROADCAST_MAC = "a1:a2:a3:a4:00:30" # 定义广播(多播)消息时要广播的目的MAC地址
BROADCAST_IP = "239.192.255.250" # 定义广播(多播)消息时的目的IP地址
BROADCAST_PORT = 30490 # 定义发送广播消息时使用的源端口号和目的端口号,SOME/IP-SD协议通常默认使用30490
SESSION_ID_OFFER = 1 # 定义用于发送offer时的session id
3.3 提供服务(Offer Service)
模拟一个ECU的服务端,向外部(其他ECU或客户端或服务)广播发送Offer(提供的服务均使用UDP通信时),用于提供可订阅的服务;
from scapy.all import *
from scapy.contrib.automotive.someip import *
from scapy.layers.l2 import Ether
from scapy.layers.inet import IP, UDP, TCP
import time
# 注意以下参数需要根据自己的实际情况配置,否则可能无法通信成功
NETWORK_ADAPTER = "Intel(R) Wi-Fi 6 AX201 160MHz" # 定义要使用的网卡
LOCAL_MAC = "01:02:03:04:05:06" # 定义网卡对应的MAC地址
LOCAL_IP = "127.0.0.1" # 定义网卡对应的IP地址(注意此处最好设置为固定的IP地址)
BROADCAST_MAC = "a1:a2:a3:a4:00:30" # 定义广播(多播)消息时要广播的目的MAC地址
BROADCAST_IP = "239.192.255.250" # 定义广播(多播)消息时的目的IP地址
BROADCAST_PORT = 30490 # 定义发送广播消息时使用的源端口号和目的端口号,SOME/IP-SD协议通常默认使用30490
SESSION_ID_OFFER = 1 # 定义用于发送offer时的session id
# 构建一个SOME/IP头,构建的原则以及参数设置请参考文档开头引用的另外两个文章
def some_ip_header():
some_ip = SOMEIP()
some_ip.srv_id = 0xffff
some_ip.sub_id = 0x1 # 在Scapy的someip模块中,该参数为1表示需要使用类型为Event,参数为0表示需要使用类型为Method
# some_ip.method_id = 0x8100
some_ip.event_id = 0x8100
some_ip.session_id = SESSION_ID_OFFER
some_ip.msg_type = SOMEIP.TYPE_NOTIFICATION
some_ip.retcode = SOMEIP.RET_E_OK
SESSION_ID_OFFER += 1
if SESSION_ID_OFFER > 0xffff:
SESSION_ID_OFFER = 1
return some_ip
# 构建一个SOME/IP-SD头以及Entries列表和Options列表,构建的原则以及参数设置请参考文档开头引用的另外两个文章
def some_ip_sd():
# 构建Options
option1 = SDOption_IP4_EndPoint() # Option有多种类型,请根据协议规定以及业务需求选择自己需要的类型并配置
option1.addr = LOCAL_IP
option1.l4_proto = 0x06 # 0x06: TCP, 0x11: UDP
option1.port = 50001 # 该端口应该是实际业务层定义的服务端的服务端口,请按照实际情况配置
option2 = SDOption_IP4_EndPoint() # Option有多种类型,请根据协议规定以及业务需求选择自己需要的类型并配置
option2.addr =