1. SOME/IP服务发现基础实现

SOME/IP服务发现基础实现 学习卡片

任务说明

本案例实现SOME/IP服务发现(Service Discovery)的最小闭环:一个服务提供者(Server)通过SD报文宣告自身服务,一个消费者(Client)通过查找报文发现该服务并完成订阅。代码基于Python + vsomeip库实现,不依赖真实ECU环境,可在本机直接运行验证。

环境依赖

  • Python 3.8+
  • 安装vsomeip库:pip install vsomeip(Linux环境需先安装Boost与vsomeip原生库,Windows可跳过本案例)

完整实现代码

import vsomeip
import time
import threading

# 服务ID与实例ID(SOME/IP标准定义)
SERVICE_ID = 0x1234
INSTANCE_ID = 0x5678
EVENTGROUP_ID = 0x0001
EVENT_ID = 0x8001

# 服务提供者(Server)端
class ServiceProvider:
    def __init__(self):
        self.app = vsomeip.Application("provider")
        self.app.init()
        self.app.register_message_handler(vsomeip.message_type_e.MT_REQUEST, self.on_request)
        self.app.register_availability_handler(self.on_availability)
        self.app.register_state_handler(self.on_state)
        self.offered = False

    def on_state(self, state):
        if state == vsomeip.application_state_e.APP_STATE_REGISTERED:
            self.app.offer_service(SERVICE_ID, INSTANCE_ID)
            self.offered = True
            print("[Provider] Service offered: 0x1234/0x5678")

    def on_availability(self, service_id, instance_id, available):
        pass  # 服务端不需要监听自身可用性

    def on_request(self, message):
        # 处理消费者发来的请求(此处为简单回显)
        response = self.app.create_response(message)
        response.set_payload(message.get_payload())
        self.app.send(response)
        print("[Provider] Request handled")

    def start(self):
        self.app.start()

# 消费者(Client)端
class ServiceConsumer:
    def __init__(self):
        self.app = vsomeip.Application("consumer")
        self.app.init()
        self.app.register_availability_handler(self.on_availability)
        self.app.register_state_handler(self.on_state)
        self.service_found = False

    def on_state(self, state):
        if state == vsomeip.application_state_e.APP_STATE_REGISTERED:
            # 查找服务
            self.app.request_service(SERVICE_ID, INSTANCE_ID)
            print("[Consumer] Requesting service 0x1234/0x5678")

    def on_availability(self, service_id, instance_id, available):
        if available:
            self.service_found = True
            print(f"[Consumer] Service found: 0x{service_id:04x}/0x{instance_id:04x}")
            # 订阅事件组
            self.app.request_event(SERVICE_ID, INSTANCE_ID, EVENT_ID, EVENTGROUP_ID)
            self.app.subscribe(SERVICE_ID, INSTANCE_ID, EVENTGROUP_ID)
            print("[Consumer] Subscribed to event group")
        else:
            self.service_found = False
            print("[Consumer] Service lost")

    def start(self):
        self.app.start()

if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print("Usage: python sd_demo.py [server|client]")
        sys.exit(1)

    role = sys.argv[1]
    if role == "server":
        provider = ServiceProvider()
        provider.start()
    elif role == "client":
        consumer = ServiceConsumer()
        consumer.start()
    else:
        print("Invalid role. Use 'server' or 'client'.")
        sys.exit(1)

运行与验证

本案例需要两个终端分别启动服务端与客户端:

# 终端1:启动服务提供者
python sd_demo.py server

# 终端2:启动消费者(等待1~2秒让服务端先完成注册)
python sd_demo.py client

通过条件:

  • 终端1输出 [Provider] Service offered: 0x1234/0x5678,表明服务已注册到SD。
  • 终端2输出 [Consumer] Service found: 0x1234/0x5678,表明消费者通过SD报文成功发现服务。
  • 终端2继续输出 [Consumer] Subscribed to event group,表明事件组订阅完成。

若两端均无报错且上述日志按序出现,则说明SOME/IP服务发现基本流程(提供者注册 + 消费者查找)实现成功。

关键说明

  • vsomeip的SD报文(OfferService/FindService)由库内部自动封装发送,本案例代码聚焦于应用层注册与查找逻辑。
  • 服务端与客户端需运行在同一网络命名空间(本机回环即可),vsomeip默认使用回环地址通信。
  • 若需跨设备运行,需在vsomeip的JSON配置文件中指定网卡IP,本案例不展开。