《AUTOSAR_SWS_SocketAdaptor》规范的主要内容包括:
- 简介和功能概述:说明了 AUTOSAR 基本软件模块 Socket Adaptor(SoAd)的功能、API 和配置。数据传输的 TCP/IP 概念在计算和电信环境中已成为标准,应用程序的寻址等覆盖在分层协议和数字分配中,而动态配置和路由是实现这些概念的核心。AUTOSAR 遵循静态通信关系概念,SoAd 模块旨在弥合这两个概念之间的差距,通过建立包含 AUTOSAR 所需信息的预确定配置并保留一些可在运行时更新的项,利用相互冲突的概念,同时将基于回调的软件体系结构与 TCP/IP 世界中的基于套接字的通信处理解耦。其主要目的是在使用 PDU(如 PDURouter)的 AUTOSAR 通信服务模块和基于套接字的 TCP/IP 堆栈之间创建一个接口,将 I-PDU ID 映射到套接字连接,反之亦然。
- 约束和假设:使用 TCP/IP 在以太网上传输数据需约 60 字节的报头信息,为避免协议开销,可对每个 PDU 使用单个套接字连接,并添加一个包含 ID 和长度信息的小 PDU 头来通过一个套接字连接传输多个 PDU,AUTOSAR 规范还包括资源保护方案作为可选项。此外,AUTOSAR 规范不涉及 UDP 或 TCP 端口号的分配,由每个实现者负责管理,也不涉及 IP 地址的管理,可以是动态(如使用 DHCP)或静态的,实现者需防止地址冲突并实现符合 IANA 地址分配。
- 对其他模块的依赖关系:SoAd 模块是 TCPIP 模块可能的上层模块之一,AUTOSAR TCP/IP 模块实现了 TCP/IP 协议族中的主要协议(如 TCP、UDP、IPv4、ARP、ICMP、DHCP、IPv6、NDP、ICMPv6、DHCPv6),并通过以太网提供基于套接字的动态通信。在 AUTOSAR 体系结构中定义了许多 SoAd 上层模块,如 PDUR(PDURouter)、UDPNM(UDPNetworkManagement)、XCP(XCPonEthernet)、SD(ServiceDiscovery)、DoIP(DiagnosticsOverIP)等,这些模块使用 SoAd 通用上层 API/配置,可指定使用的服务类型。
- 功能规范:SoAd 通过 TCP/IP 网络实现基于 PDU 的通信,将 AUTOSAR I-PDU 映射到由 SoAd 配置和维护的套接字连接。当多个 I-PDU 使用套接字连接时,可在每个 I-PDU 前添加一个 SoAd PDU 头。消息接受策略用于定义如何接受远程节点的 TCP 连接和 UDP 数据报文,套接字连接可通过来自上层的请求自动或手动打开,同时定义了对于套接字连接的断开和恢复的策略。SoAd 的上层可使用 IF-API 和 TP-API 的接口来进行 PDU 的传输和接收,还可通过定义 PDU 路由组有选择地使能或禁止套接字连接进出的 PDU 报文的路由,一个 IF-PDU 也可转发给多个套接字连接,或者从一个套接字连接收到的消息可作为不同的 IF-PDU 转发给同一或不同的 SoAd 上层(PDU Fan-Out)。另外,SoAd 模块不提供任何方法来调整 PDU 中的位或字节顺序。
套接字连接方面,TCP/IP 通信基于 Internet 套接字,它是通信链路的端点,由元组 IP 地址和端口标识。在 UDP 套接字中用于无连接通信,而 TCP 套接字用于面向连接的通信,要求一方建立连接,另一方接受传入的请求,两个站之间可建立多个连接,每个连接由不同的套接字处理,至少需使用一个不同的端口号,其确认方案可保证跨消息的字节顺序的正确性。SoAd 定义了套接字连接,包含本地套接字和远程套接字信息以及其他连接参数,每个套接字连接由唯一的标识符(SoConID)来标识,为支持多个通信伙伴,具有相同连接参数的套接字可分组为套接字连接分组。
一、SoAd使用场景及与PduR的关系
(一)使用场景示例
假设在一个汽车电子系统中,有多个电子控制单元(ECU)需要进行通信,例如发动机控制单元(ECU1)、仪表盘控制单元(ECU2)和车载娱乐系统控制单元(ECU3)。
ECU1负责收集发动机的各种数据,如转速、温度、油压等信息,并将这些数据封装成PDU(协议数据单元)格式。这些数据需要传输给ECU2,以便在仪表盘上显示发动机的实时状态,同时也需要传输给ECU3,用于在车载娱乐系统中提供相关的车辆信息展示。
SoAd模块在这个场景中的作用就是负责建立和管理这些ECU之间的以太网通信连接。它会根据配置信息,将来自ECU1的不同类型的PDU(对应不同的发动机数据)映射到合适的套接字连接上,然后通过以太网将这些数据发送到ECU2和ECU3。例如,将发动机转速数据的PDU通过特定的套接字连接发送到ECU2的特定端口,以便仪表盘能准确获取并显示转速信息;将发动机温度和油压数据的PDU发送到ECU3的相应端口,用于车载娱乐系统的信息展示。
(二)与PduR的关系
PduR(PDU路由器)主要负责在AUTOSAR通信栈中路由PDU,它决定了PDU从源模块到目标模块的传输路径。SoAd与PduR紧密协作,PduR将来自不同源(如ECU1中的传感器数据采集模块)的PDU路由到SoAd模块,SoAd则负责将这些PDU通过以太网发送到目标ECU(如ECU2和ECU3)。SoAd可以看作是PduR与以太网之间的桥梁,PduR将PDU传递给SoAd后,SoAd根据其配置的套接字连接和通信参数,将PDU转换为适合在以太网上传输的格式并发送出去。同时,当SoAd接收到来自以太网的PDU时,会将其传递回PduR,由PduR继续路由到目标模块(如仪表盘显示模块或车载娱乐系统中的相关模块)进行处理。
二、SoAd工作原理及数据发送和接收过程的C++源代码示例
以下是一个简化的C++代码示例,用于说明SoAd的主要工作原理以及数据发送和接收的过程。请注意,这只是一个概念性的示例,实际的SoAd实现会更加复杂,并且依赖于AUTOSAR的运行时环境和相关库。
#include <iostream>
#include <vector>
#include <unordered_map>// 假设这是一个表示PDU的简单结构体
struct Pdu {int pduId;std::vector<uint8_t> data;
};// 表示套接字连接的结构体
struct SocketConnection {int socketId;std::string localAddress;int localPort;std::string remoteAddress;int remotePort;
};// SoAd模块类
class SoAdModule {
private:// 存储套接字连接的映射,以SoConId为键std::unordered_map<int, SocketConnection> socketConnections;// 存储PDU路由信息的映射,以PduId为键std::unordered_map<int, SocketConnection> pduRoutes;public:// 初始化SoAd模块,配置套接字连接等void init() {// 模拟配置一些套接字连接SocketConnection conn1 = {1, "192.168.1.10", 5000, "192.168.1.20", 5001};socketConnections[1] = conn1;SocketConnection conn2 = {2, "192.168.1.10", 5002, "192.168.1.30", 5003};socketConnections[2] = conn2;// 配置PDU路由,假设PduId 101通过套接字连接1发送,PduId 102通过套接字连接2发送pduRoutes[101] = conn1;pduRoutes[102] = conn2;}// 发送PDU的函数void sendPdu(Pdu pdu) {// 根据PDU的Id查找对应的套接字连接if (pduRoutes.find(pdu.pduId)!= pduRoutes.end()) {SocketConnection& conn = pduRoutes[pdu.pduId];std::cout << "Sending PDU with Id " << pdu.pduId << " via socket connection: " << conn.socketId << std::endl;// 这里可以添加实际的网络发送代码,例如使用套接字库发送数据// 假设使用send函数(实际需要包含相关头文件和错误处理等)// send(socket, pdu.data.data(), pdu.data.size(), 0);} else {std::cerr << "No socket connection configured for PDU with Id " << pdu.pduId << std::endl;}}// 接收数据的函数,这里只是模拟接收并路由PDUvoid receiveData(int socketId, const std::vector<uint8_t>& data) {// 查找接收数据的套接字连接对应的PduIdfor (auto& it : pduRoutes) {if (it.second.socketId == socketId) {Pdu receivedPdu = {it.first, data};std::cout << "Received data for PDU with Id " << receivedPdu.pduId << std::endl;// 这里可以将接收到的PDU传递给PduR或其他模块进行进一步处理// 假设调用PduR的接收函数(实际需要实现相关接口)// PduR.receivePdu(receivedPdu);return;}}std::cerr << "Received data on unknown socket connection with Id " << socketId << std::endl;}
};
在上述代码中:
SoAdModule
类表示SoAd模块,它在init
函数中模拟了套接字连接的配置和PDU路由的设置。sendPdu
函数根据传入的PDU的pduId
查找对应的套接字连接,并模拟了发送数据的过程(实际需要使用真实的网络发送函数)。receiveData
函数根据接收数据的套接字连接socketId
查找对应的pduId
,构建接收到的Pdu
对象,并模拟了将其传递给其他模块(如PduR)进行处理的过程。
实际应用中,SoAd模块会与操作系统的套接字库、AUTOSAR的网络协议栈以及其他相关模块(如PduR)紧密集成,以实现可靠的以太网数据通信。同时,还需要处理各种网络事件、错误情况、连接管理等复杂的任务,以上代码仅为了帮助理解其基本工作原理。