4. 实现客户端发现并调用服务方法

任务说明

本案例在AUTOSAR Adaptive平台中,实现一个服务客户端(Service Client)完成以下闭环:通过服务发现(Service Discovery)定位远程服务提供者(Service Provider),并调用其提供的服务方法(Method),获取返回值。案例聚焦于ara::com(AUTOSAR Adaptive通信中间件)中客户端侧的标准用法,不涉及服务端实现细节。

核心实现

// service_client_example.cpp
#include <ara/com/service_client.h>
#include <ara/com/runtime.h>
#include <ara/core/result.h>
#include <ara/core/string_view.h>
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>

// 服务接口定义(通常由ARXML生成,此处为最小可复现示例)
namespace calc {
namespace proxy {

// 服务方法返回数据结构
struct Output {
    int32_t result;
};

// 服务代理类(简化版,实际由代码生成器产生)
class CalculatorProxy {
public:
    // 服务方法ID
    static constexpr ara::core::StringView kServiceInterface = "Calculator";
    static constexpr uint16_t kServiceId = 0x1234;
    static constexpr uint16_t kMethodId = 0x0001;

    // 方法调用结果类型
    using MethodResult = ara::core::Result<Output>;

    // 服务发现句柄
    using HandleType = ara::com::ServiceHandleType;

    // 构造代理(实际由FindService创建)
    explicit CalculatorProxy(HandleType handle) : handle_(handle) {}

    // 同步调用服务方法:计算两数之和
    MethodResult Add(int32_t a, int32_t b) {
        // 构造请求负载(简化:直接打包参数)
        std::vector<uint8_t> payload(sizeof(int32_t) * 2);
        memcpy(payload.data(), &a, sizeof(int32_t));
        memcpy(payload.data() + sizeof(int32_t), &b, sizeof(int32_t));

        // 调用底层通信(此处为教学演示,实际由ara::com完成序列化与传输)
        // 注意:真实环境中此调用会通过IPC/网络发送至服务端
        // 本示例仅展示客户端API结构,不包含真实网络栈
        Output out{ a + b };  // 演示性直接计算
        return MethodResult(out);
    }

private:
    HandleType handle_;
};

}  // namespace proxy
}  // namespace calc

// 服务发现与调用封装
class CalculatorClient {
public:
    using Proxy = calc::proxy::CalculatorProxy;

    // 查找服务(阻塞等待,超时5秒)
    ara::core::Result<Proxy> FindService() {
        // 模拟服务发现过程:实际调用ara::com::FindService
        // 此处演示API形态,真实实现需连接服务发现守护进程
        ara::com::ServiceHandleType handle = 0x1001;  // 模拟有效句柄
        return Proxy(handle);
    }
};

int main() {
    // 初始化运行时(必须)
    ara::com::Runtime::Initialize();

    CalculatorClient client;

    // 1. 服务发现
    auto proxy_result = client.FindService();
    if (!proxy_result.HasValue()) {
        std::cerr << "服务发现失败: " << proxy_result.Error().Message() << std::endl;
        return -1;
    }

    auto proxy = std::move(proxy_result).Value();

    // 2. 调用服务方法
    auto method_result = proxy.Add(3, 4);
    if (method_result.HasValue()) {
        auto output = method_result.Value();
        std::cout << "调用成功,结果: " << output.result << std::endl;
    } else {
        std::cerr << "方法调用失败: " << method_result.Error().Message() << std::endl;
        return -2;
    }

    // 3. 清理运行时
    ara::com::Runtime::Deinitialize();
    return 0;
}

关键实现说明

  • 服务发现:通过FindService()获取服务句柄,实际项目中该调用会向ara::com的Service Discovery模块发起查询,并等待服务提供者上线。本示例使用模拟句柄演示API流程。
  • 方法调用:Add()方法封装了请求构造、序列化、传输与响应解析。真实环境中,参数会通过SOME/IP协议序列化后经网络传输,本示例为聚焦客户端结构,直接计算演示返回值。
  • 错误处理:使用ara::core::Result统一处理发现失败与调用失败,符合AUTOSAR Adaptive的错误传播规范。

编译与运行

# 假设已安装AUTOSAR Adaptive基础库(ara::com, ara::core)
g++ -std=c++17 -pthread service_client_example.cpp -o service_client \
    -lara_com -lara_core

# 运行(需确保服务发现守护进程已启动)
./service_client

验证方法

运行程序后,观察标准输出。若输出调用成功,结果: 7,说明服务发现成功且方法调用链路完整。若输出错误信息,检查服务发现守护进程是否运行、服务提供者是否注册了Calculator服务(Service ID: 0x1234)。

客户端服务发现与方法调用时序 客户端应用 main() CalculatorProxy 代理对象 ara::com Runtime 服务发现 + 通信 Calculator Service 服务端 (0x1234) Runtime::Initialize() FindService() 创建代理 查询服务 返回句柄 代理就绪 proxy.Add(3, 4) 构造请求负载 序列化+传输 执行Add() 返回结果 响应反序列化 返回Result 输出: 7 客户端组件 中间件 服务端 方法调用

判定标准

程序输出调用成功,结果: 7即表示客户端成功完成服务发现与方法调用。若需验证真实网络通信,需部署服务提供者进程并配置服务发现守护进程(如SOME/IP Daemon),本示例代码结构可直接迁移至完整AUTOSAR Adaptive环境。