精华内容
下载资源
问答
  • 摘要:针对智能家居内部网络低成本、短距离、低数据速率的通信与组网需求,设计了一种基于CC1101的433 MHz射频通信协议栈,并实现了以嵌入式操作系统μC/OS-II与微控制器STM32F407为基础的智能网关。该智能网关搭载...
  • 基金会现场总线通信协议栈一致性测试rar,现场总线,一致性测试,互操作测试,协议栈
  • 传统的TCP/IP协议重点在于保证数据传输的可靠性及流量控制,而在实时性要求相对较...为此,对基于TCP/IP协议的嵌入式通信协议栈进行了分析,针对通信中的TCP拥塞控制问题进行了改进,有效地提高了TCP/IP协议的实时性。
  • 研究了嵌入式TCP/IP通信协议栈在Xilinx FPGA上的实现,介绍了其软硬件的系统组成和原理,提出一种实时操作系统上TCP/IP协议栈的高效工作模式,并在Virtex5 FPGA上移植成功。通过建立测试平台进行数据传输测试,证明...
  • LIN通信协议栈

    2017-12-13 20:25:31
    LIN通用协议栈,仅需要底层提供Break探测功能,就能快速实现LIN主从通信,已经实际用于很多实际项目,仅供参考![代码全为个人劳动所编]
  • 为了简化汽车故障诊断系统的设计,提出了一种基于通信协议栈的汽车故障诊断实现方法。协议栈以IS015765为核心,实现数据的读写,同时利用计算机对接收到的数据做进一步分析,以便迅速地判断出故障产生的原因,并以此为...
  • CAN通信协议栈梳理 概念 配置方法

    CAN通信协议栈梳理

    1. 概念
    2. 配置方法
    展开全文
  • AUTOSAR中CAN通信协议栈概述 COM模块 AUTOSAR COM是位于RTE和PduR之间的服务层模块,主要用于与RTE之间的信号交互,对信号进行打包和解包。另外在该模块中还可以配置IPDU的通信周期、通信周期偏移量、IPDU Group等...

    AUTOSAR中CAN通信协议栈概述

    在这里插入图片描述
    在这里插入图片描述

    COM模块

    AUTOSAR COM是位于RTE和PduR之间的服务层模块,主要用于与RTE之间的信号交互,对信号进行打包和解包。另外在该模块中还可以配置IPDU的通信周期、通信周期偏移量、IPDU Group等。

    1、I-PDU
    I-PDU包含从通信栈中某一模块接收到的消息或需要发送给某一模块的消息。
    2、I-PDU组
    如果我们有大量的I-PDU,则可以将它们分为不同的组,通常至少分为两个组,一个为TxGroup,一个为RxGroup。
    3、信号
    I-DPU可以包含一个或多个信号,可以理解为一个I-PDU为一帧CAN消息,信号就是dbc中定义的。
    4、信号组
    如果需要将多个信号发送到同一I-PDU,则信号可以进一步形成信号组。
    COM模块包含两个主要的部分,分别为ComGeneral和ComConfig。
    ComGeneral(多重性:1)
    1、ComConfigurationUseDet:如果此布尔参数设置为ON,则任何当COM模块出现错误时,会调用Det_ReportError函数,记录在DET模块中(多重性:0.1)。
    2、ComCancellationSupport:这是一个布尔参数,用于启用/禁用用于取消PDU传输请求的取消功能。(多重性:0.1)。
    3、ComEnableSignalGroupArrayApi:这是一个布尔参数,用于激活/禁用信号组阵列访问API。(多重性:1)。
    4、ComSupportedIPduGroups:它是一个整数参数,用于说明所支持的IPDU组的最大数量。(多重性:1)。
    5、ComVersionInfoApi:布尔参数,用于激活/禁用版本信息API Com_GetVersionInfo。(多重性:1)。
    6、ComRetryFailedTransmitRequests:如果此参数设置为true,则启用重试失败的传输请求。(多重性:0.1)。
    7、ComEnableMDTForCyclicTransmission:如果启用此选项,则它将在I-PDU的循环传输和重复传输之间提供最小延迟时间监视。(多重性:0.1)。
    ComConfig(多重性:0.1)
    它包含四个容器,分别为ComSignals、ComIPdus、ComIPduGroups、ComSignalGroups。它还具有用于传输模式配置,信号网关配置,时基配置和过滤器参数配置的配置参数。
    ComIpdu(多重性:1)
    该容器用于为不同的IPDU参数提供定义,如果没有该参数,则无法通过COM模块进行通信。ComIPdu也通过ComPduIdRef链接到PDU。I-PDU包含一个或多个信号和/或信号组。以下是ComIpdu的一些基本属性。
    1、ComIPduHandleId:这是分配为该IPDU的ID的数字值。此ID用于在各种发送和接收API调用以及相应的回调API中引用此IPDU。(多重性:0.1)。
    2、ComPduIdRef:它提供对COM栈的全局PDU结构的引用。(多重性:1)。
    3、ComIPduGroupRef:它是指IPDU所属的IPDU组。(多重性:0 … *)。
    4、ComIPduSignalRef:提供对该IPDU中包含的所有信号的引用。一个IPDU可以包含一个或多个单独的信号。(多重性:0 … *)。、
    5、ComIPduSignalGroupRef:提供对此IPDU中包含的所有信号组的引用(多重性:0 … *)
    6、ComIPduCallout:此参数可定义相应I-PDU的callout函数的名称,该函数在接收IPDU时或在发送PDU之前调用。(多重性:0 … 1)。
    7、ComIPduDirection:定义I-PDU是为发送(SEND)PDU还是为接收(RECEIVE)PDU。(多重性:1)。
    8、ComIPduSignalProcessing: 用于配置信号是立即处理还是周期性处理,分别对应immediate或DEFERRED模式。(多重性:1)。
    如果将ComIPduDirection设置为SEND,则需要设置其他参数,例如传输是周期的还是混合型的等等。这是通过添加ComTxIPdu对象来添加的。
    ComIpduGroup(多重性:1)
    它包含COM模块的IPDU组的配置参数。如果不包含ComIPduGroup容器,则未定义IPDU组。在这种情况下,无法通过COM模块进行通信。(多重性:1)
    1、ComIPduGroupHandleId:用作此IPDU组ID的数值。API调用需要它来启动和停止IPDU组。(多重性:1)
    2、ComIPduGroupGroupRef:它提供对包括该IPDU组的所有IPDU组的引用。(多重性:0 … *)
    ComSignal
    IPDU可以由一个或多个信号组成。来自RTE不同应用程序的这些信号在被传输到PduR之前被打包到PDU中。该容器提供各种参数来配置PDU中的信号位位置,信号位大小和其他属性。
    1、ComHandleId:这是分配给每个信号ID的数字值。与信号操作有关的不同API调用需要它。(多重性:0 … 1)。
    2、ComTimeoutFactor:它定义了监视的超时时间。(多重性:0…1)
    3、ComTransferProperty:以下选项定义此信号是否可以触发相应IPDU的传输;(多重性:0 … 1)
    我们可以设置以下五个选项之一:
    TRIGGERED
    PENDING
    TRIGGERED_ON_CHANGE,
    TRIGGERED_WITHOUT_REPETITION TRIGGERED_ON_CHANGE_WITHOUT_REPETITION
    4、ComBitPosition:指出信号在IPDU中的开始位置,(多重性:1)。
    5、ComBitSize:它定义信号的大小(以位为单位)。(多重性:0 … 1)
    6、ComSignalEndianess:定义信号网络表示的字节排序。可以是BIG_ENDIAN,LITTLE_ENDIAN,OPAQUE。(多重性:0 … 1)
    7、ComSignalInitValue:用于设置信号的初始值。(多重性:0 … 1)
    8、ComSignalLength:它指定UINT8 [n]类型的n(以字节为单位:1 … 8)。对于其他类型,它将被忽略。(多重性:0 … 1)
    9、ComSignalType:它指定符合BOOTEAN,SINT8,UINT8等。(多重性:1)
    10、ComTimeoutNotification:定义发生超时时在发送方或接收方要调用的函数的名称(多重性:0 … 1)
    ComSignalGroup
    然后,当我们需要向同一IPDu发送或接收多个信号时,可以将这些信号组合在一起以形成一个信号组。
    此容器包含名称与ComSignal容器相似的参数,并且对信号组具有完全相同的作用。因此,在本节中,我仅提及参数名称,要了解其行为,请参阅ComSignal部分。
    ComHandleId(多重性:0 … 1)
    ComTimeoutFactor(多重性:0 … 1)
    ComFirstTimeoutFactor(多重性:0 … 1)
    ComTransferProperty(多重性:0 … 1)
    ComNotification(多重性:0 … 1)
    ComInvalidNotification(多重性:0 … 1)
    ComErrorNotification(多重性:0 … 1)
    ComTimeoutNotification(多重性:0 … 1)

    PduR模块

    PduR的作用是为通信协议栈中的不同总线的IPDU提供路由路径。例如它将接收的IPDU路由至COM、Dcm等模块,或者将COM模块需要发送的IPDU路由至CanIf模块,最后传送至芯片的CAN Driver,将信号发送至总线。

    PduRBswModules(多重性:0 … *)
    每个容器都描述了PDU路由器必须连接的特定BSW模块。添加PduRBswModule时,容器的简称必须与Bsw模块的名称匹配,例如CanIf。
    PdurGeneral(多重性:1)
    这是PduR模块的子容器,它指定PDU路由器的常规配置参数。以下是一些基本配置参数。
    1、PduRDevErrorDetect:如果启用,它将默认错误跟踪器(Det)检测和通知打开。(多重性:1)
    2、PduRVersionInfoApi:如果设置为true,则PduR_GetVersionInfo API可用。(多重性:1)
    PduRRoutingTables(多重性:1)
    它表示路由路径表。此路由表允许使用多个配置,这些配置用于在同一配置中创建多个路由表。
    1、PduRConfigurationId:它提供了使用PduR API读取的PduR配置的配置的标识。(多重性:1)
    2、PduRMaxRoutingPathCnt:给出所有路由表中最大路由路径数。(多重性:1)
    3、PduRMaxRoutingTableCnt:它给出了路由表的最大数量。(多重性:1)
    PduRSrcPdu
    这是PduRRoutingPath容器的子容器,它指定要路由的PDU的源。
    1、PduRSourcePduHandleId:这是PDU路由器分配的PDU标识符。(多重性:1)
    2、PduRSrcPduRef:此参数提供对唯一PDU标识符的引用,该标识符表示PDU的源地址。(多重性:1)
    PduRDestPdu
    这是PduRRoutingPath容器的子容器,并为要路由的PDU指定一个目的地。
    1、PduRDestPduHandleId:由PDU路由器分配的PDU标识符,通信接口和传输协议模块使用该PDU标识符进行确认。(多重性:0 … 1)
    2、PduRDestPduDataProvision:此参数指定如何以
    PDU_DIRECT或PDUR_TRIGGERTRANSMIT提供数据。(多重性:0 … 1)
    3、PduRDestPduRef:它提供参考唯一的PDU标识符,表示PDU路由的目的地(多重性:1)
    4、PduRDestTxBufferRef:提供对用于单帧路由的通信接口网关和传输协议网关所需的缓冲区的引用。(多重性:0 … 1)

    CanTp模块

    Tp表示传输协议。该模块是特定于总线,其配置取决于基础总线协议,可以是CAN、LIN、CANFD等总线。该模块主要用于长报文的分段发送,以及对分段报文进行重组。

    Bus SM 模块

    总线状态管理模块负责相应总线状态机的管理和总线故障的处理。它可以基于CAN总线的CanSM,或者是基于LIN总线的LinSM等。

    CAN状态管理器(CanSM)
    CAN状态管理器(CanSM)是通信服务层的成员,该层与通信硬件抽象层和系统服务层进行交互。CanSM模块负责CAN状态机的管理,包括CanTrcv、CanIf、CAN Driver的状态机切换。CanSM模块具有以下容器用于其配置。
    CanSMGeneral(多重性:1)
    它包含CanSM模块的通用预配置参数。
    1、CanSMDevErrorDetect:用于打开或关闭开发错误检测API是否可以调用。(多重性:1)
    2、CanSMMainFunctionTimePeriod:它定义MainFunction的循环周期(单位为秒)(多重性:1)
    3、CanSMVersionInfoApi:用于打开或关闭版本信息API CanSM_GetVersionInfo。(多重性:1)
    CanSMManagerNetwork(多重性:1 … *)
    该容器包含用于确定底层CanController(即每个CAN网络)处理方式的CAN网络特定参数。
    1、CanSMModeRequestRepetitionTime:它确定CanSM模块将使用CanIf模块的API重复模式更改请求的持续时间。(多重性:1)
    2、CanSMModeRequestRepetitionMax:它确定模式请求重复的最大次数,如果超过次数CanSM模块向Det报告开发错误。(多重性:1)
    每个CAN网络的CanSMConfiguration容器都有一个CanSMManagerNetwork。
    它包含每个CAN网络的CAN网络特定参数。
    1、CanSMBorCounterL1ToL2:它定义总线断开错误的计数,从快恢复切换到慢恢复的门槛值。(多重性:1)
    2、CanSMBorTimeL1:以秒为单位,定义快恢复的持续时间。(多重性:1)
    2、CanSMBorTimeL2:以秒为单位,定义慢恢复的持续时间。(多重性:1)
    CanSMController(多重性:1 … *)
    每个容器引用一个唯一的CAN控制器。
    1、CanSMControllerId:引用一个特定CAN控制器的唯一标识符。(多重性:1)

    Bus Trcv Driver模块

    它是ECU抽象层的一部分。它可以是用于CAN收发器的CanTrcv,用于以太网收发器的EthTrcv,用于Flexray收发器的FrTrcv等。此模块用于对收发器进行初始化配置,它提供独立于控制器硬件的用于启动传输的服务和用于通知接收事件的回调函数。

    Bus Driver

    该模块是AUTOSAR MCAL层的一部分(例如:CanDrv,LinDrv,FrDrv),它实际上与ECU的底层硬件进行交互,并为其上层提供独立于硬件的接口。此模块取决于硬件,并且驱动程序代码可能会根据基础硬件而有所不同。BusIf是唯一可以访问此总线驱动程序的模块。

    CanIf模块
    CANIf模块位于通信栈中的通信服务层和通信驱动程序层之间。它负责控制CAN驱动程序模块的初始化,并在消息的接收(CanIf_RxIndication)或传输(CanIf_TxConfirmation)时为CAN驱动程序模块提供通知服务。CANIf模块独立于硬件。
    CanIfPublicCfg(多重性:1)
    该容器包含CanIf的公共配置参数。
    1、CanIfDevErrorDetect:如果设置为true,它将打开开发错误检测和通知功能。如果设置为false,则关闭。(多重性:1)
    2、CanIfPublicVersionInfoApi:启用或禁用用于读取版本信息的API。(多重性:1)
    该容器包含CanIf的专用配置参数。
    1、CanIfPrivateDlcCheck:选择是否支持DLC检查。如果启用,则如果该帧的DLC小于配置的DLC,则该帧将不会转发到上层。如果接收到的帧的DLC大于或等于配置的DLC,则将帧转发到上层。
    CanIfCtrlDrvCfg(多重性:1 … *)
    1、它提供了基础CAN驱动程序模块的配置参数。一个CanIfDrvCfg引用一个Can Driver模块。
    CanIfInitCfg(多重性:)
    它包含CanIf的所有初始化参数。此容器至少有一个实例。它定义了所有与PDU相关的配置。
    CanIfBufferCfg(多重性:0 … *)
    它是CanIfInitCfg的子容器。此容器包含传输缓冲区配置。必须为将用于传输帧的每个CanController添加此容器的一个实例。
    CanIfTxPduCfg(多重性:0 … *)
    它是CanIfInitCfg的子容器。它包含发送CAN L-PDU的配置参数。每次需要发送CAN L-PDU时都要对其进行配置。
    1、CanIfTxPduCanId:定义发送CAN标识符,11位标准帧或29位扩展帧。(多重性:1)
    2、CanIfTxPduCanIdType:定义发送CAN标识符的类型,是标准格式(11位)还是扩展格式(29位)。(多重性:1)
    3、CanIfTxPduDlc:定义发送L-PDU的数据长度(以字节为单位)。范围是0到8个字节。(多重性:1)
    CanIfRxPduCfg(多重性:0 … *)
    它是CanIfInitCfg的子容器。它包含每个接收到的CAN L PDU的配置参数。
    CanIfRxPduCanId:定义接收CAN标识符,11位标准帧或29位扩展帧。(多重性:1)
    CanIfRxPduCanIdType:定义接收CAN标识符的类型,是标准格式(11位)还是扩展格式(29位)。(多重性:1)
    CanIfRxPduDlc:定义接收L-PDU的数据长度(以字节为单位)。范围是0到8个字节。(多重性:1)

    CAN驱动
    该容器保存单个CAN驱动程序的配置参数。
    CanGeneral(多重性:1)
    提供模块范围的配置,其中包含常规的CanDevErrorDetection和CanVersionInfoApi。
    1、CanDevErrorDetectio:启用/禁用开发错误检测和通知。(多重性:1)
    2、CanVersionInfoApi:启用/禁用版本信息的API。(多重性:1)
    CanConfigSet(多重性:1)
    它包含CAN控制器和CAN硬件对象的配置。它是CAN驱动程序的多配置集容器。
    CanController(多重性:1)
    CanBusoffProcessing:设置busoff的处理方式,是中断还是轮询。=。(多重性:1)
    CanControllerActivation:定义CAN控制器是否处于激活状态以进行配置。(多重性:1)
    CanControllerId:它提供每个CAN驱动程序唯一的控制器ID。(多重性:1)
    CanRxProcessing:设置接收的处理方式,是中断还是轮询。(多重性:1)
    CanTxProcessing:设置发送的处理方式,是中断还是轮询。(多重性:1)
    CanWakeupProcessing:设置唤醒的处理方式,是中断还是轮询。(多重性:1)
    CanControllerDefaultBaudrate:提供对Can Controller的波特率配置容器的引用。
    CanControllerBaudrateConfig(多重性:1 … *)
    该容器包含每个CAN控制器与位时序相关的配置参数。
    CanControllerBaudRate:设置控制器的波特率,以kbps为单位。(多重性:1)
    CanControllerPropSeg:它定义时间量中的传播延迟。(多重性:1)
    CanControllerSeg1:它定义时间段中的相位段1。(多重性:1)
    CanControllerSeg2:定义时间段中的相位段2。(多重性:1)
    CanControllerSyncJumpWidth:它定义控制器在时间量上的同步跳转宽度。(多重性:1)。
    CanFilterMask(多重性:0 … *)
    此容器包含CANFilterMask的配置参数。为CAN控制器设置了ID掩码,以基于CAN id字段过滤出接收到的CAN消息。总线上的所有ECU都接收总线上传输的所有CAN数据包,但是它会根据其过滤器掩码过滤掉无关的数据包。
    1、CanFilterMaskValue:它描述用于基于硬件的CAN标识符过滤的掩码值。如果EXTENDED或MIXED类型的CAN帧,则使用29位掩码,而对于STANDARD CAN帧类型,则使用11位掩码。(多重性:1)

    展开全文
  • 通用通信协议栈完善总结

    千次阅读 2016-01-06 00:24:36
    一切都是最好的安排,14年的6月份,开始把通用通信协议栈纳入一个构件层面的规划,到第一版颤颤兢兢下线,再到后续的项目应用,及面对灵活性的优化,到性能的优化,转眼间经历了有一年半的时间,到本月的TCPServer...

    一切都是最好的安排,14年的6月份,开始把通用通信协议栈纳入一个构件层面的规划,到第一版颤颤兢兢下线,再到后续的项目应用,及面对灵活性的优化,到性能的优化,转眼间经历了有一年半的时间,到本月的TCPServer开始在项目中使用,基本上整个通信组件中的所有通信模块和协议栈都开始应用于产品和项目中了。

    几次大的变更总结:

    1、第一版,通用通信协议栈的规划设计阶段,在几年的工控行业应用中,做了很多面向设备的通信协议开发,但是在开发过程中,发现与设备交互因为设备厂家的协议不统一,造成了协议代码编写时,也及其的不统一,彼时需要一个通用的通信构件部分,能把大部分的通信封包解包的过程自动化,开发人员可以只关心具体的协议接口编写即可,至于数据包的调度、中转、分发、缓存、排队等等,都可以不去考虑,抱着这个目的,开始了最早的通用通信组件开发。

    同时第一版还要解决架构设计问题,调度设计问题等,由于对TCP、UDP的会话连接,前期有过一定的准备,包括线程池、调度服务的设计都已做过,但没有统一到一起,初始架构也就开始慢慢拼凑了。

    因为是要打造一款底层的通用通信组件,那就与具体的设备和上层业务无关。作为设备和业务数据的桥梁转化部分,就需要通过软件工程,进行剥离,软件设计的核心就是封装变化,如何能把变化抽象化,最终落到具体的实现上其实是要实现4个变化部分,业务系统的结构化数据,包括发给设备的请求数据、从设备接收后的应答数据,但是有了这两部分还不行,设备是没法识别内存中的结构化数据的,那还需要一部分转化,怎样从请求数据转化到符合设备通信的字节流数据,以及从设备反馈的字节流数据,转化为应答结构化数据,剩余其他的部分就全部是具体的通信相关了,可以封装起来了。整个通信部分,就可以分成两大部分,输入和输出,因此通信接口也就定义出来了。

    同时围绕输入输出部分,有对应的状态反馈和回调,则引入了状态通知部分。

    下面就是定义的通信接口,但是在第一版中因为想设计的太高大上,预估不足,曾经加了很多接口函数进去,后来发现通信就是一入一出两部分,围绕这个,把太多的会引起歧义的接口部分全部去掉了。

      /// <summary>
        /// 通信接口
        /// </summary>
        /// <typeparam name="TRequest">请求数据类型</typeparam>
        /// <typeparam name="TResponse">应答数据类型</typeparam>
        public interface ICommunication<TRequest,TResponse> 
            where TRequest:BaseRequestData 
            where TResponse : BaseResponseData
        {
            /// <summary>
            /// 启动
            /// 如果打开失败,会自动尝试关闭掉
            /// </summary>
            void Open();
            /// <summary>
            /// 是否开启
            /// </summary>
            bool IsOpen { get; }
            /// <summary>
            /// 请求发送
            /// 不建议与异步请求交错调用,会引起线程冲突
            /// </summary>
            /// <param name="request">请求发送的数据</param>
            bool Request(TRequest request);
            /// <summary>
            /// 异步请求数据,在其他线程上
            /// 不建议与同步请求交错调用,会引起线程冲突
            /// </summary>
            /// <param name="request">请求发送的数据</param>
            /// <param name="ex">处理异常信息</param>
            bool TryASyncRequest(TRequest request,out Exception ex);
            /// <summary>
            /// 请求数据,根据会话ID发送,
            /// 一般用于并发处理场合,根据ID来确认具体的发送会话,
            /// 用于服务监听应答场合
            /// 不建议与异步请求交错调用,会引起线程冲突
            /// </summary>
            /// <param name="sessionID">会话ID</param>
            /// <param name="request">请求发送的数据</param>
            bool Request(string sessionID,TRequest request);
            /// <summary>
            /// 广播数据,面向所有的连接,用于小连接数场合
            /// </summary>
            /// <param name="requestData">请求数据</param>
            void RequestBroadCast(TRequest requestData);
            /// <summary>
            /// 发送请求完成事件,同步到应答处理线程上,用于发送请求与应答请求,在应答线程上进行复合处理
            /// </summary>
            event RequestCompletedHandler<TRequest> OnRequestCompleted;
            /// <summary>
            /// 数据应答
            /// 异步线程上消息队列响应
            /// </summary>
            event ResponseHandler<TResponse> OnResponseBuffer;
            /// <summary>
            /// 异常信息响应
            /// 异步线程上消息队列响应
            /// </summary>
            event InfoHandler<ResponseInfo> OnResponseInfo;
            /// <summary>
            /// 操作状态
            /// </summary>
            event ResponseHandler<OperateStatus> OnOperateStaus;
            /// <summary>
            /// 会话构建后触发
            /// </summary>
            event SessionHandler OnSessionAdded;
            /// <summary>
            /// 会话从链表中移除后触发
            /// </summary>
            event SessionHandler OnSessionRemoved;
            /// <summary>
            /// 关闭
            /// </summary>
            void Close();
            /// <summary>
            /// 监听的地址和端口
            /// </summary>
            string EndPort { get; set; }
        }

    接口是服务于应用的边界的,但是最终还是要转化到具体的实现,包括:TCP客户端长短连接、TCP 服务端并发模型中的长短连接、UDP通信、串口通信等,具体的通信是要按照接口规范实现的,同时还要实现连接会话管理、调度管理等,分析中发现会话管理、调度管理等,已经是与具体的通信方式无关了,因此再抽象一层,在一个通用的抽象类中实现调度相关,这里包括了连接池、会话池、调度池、缓存排队、数据包分发等一系列核心实现。

     /// <summary>
        /// 通信基类
        /// </summary>
        /// <typeparam name="TRequest">请求数据类型</typeparam>
        /// <typeparam name="TResponse">应答数据类型</typeparam>
        public abstract class BaseCommunication<TRequest,TResponse> 
            : ICommunication<TRequest,TResponse>
            where TRequest : BaseRequestData
            where TResponse : BaseResponseData
        {
            /// <summary>
            /// 响应处理消息队列,用于应答排队
            /// </summary>
            private IMessageFIFO responseMessageFIFO = null;
            /// <summary>
            /// 是否正在关闭
            /// </summary>
            protected volatile bool onClosing = false;
            /// <summary>
            /// 启动
            /// 如果打开失败,会自动尝试关闭掉
            /// </summary>
            public abstract void Open();
            /// <summary>
            /// 是否开启
            /// </summary>
            public bool IsOpen
            {
                get
                {
                    if (responseMessageFIFO == null)
                    {
                        return false;
                    }
                    return responseMessageFIFO.IsOpened;
                }
            }
            /// <summary>
            /// 关闭
            /// </summary>
            public abstract void Close();
            #region 请求写入数据
            /// <summary>
            /// 请求发送的数据
            /// </summary>
            /// <param name="data">请求数据</param>
            public virtual bool Request(TRequest data)
            {
                throw new NotImplementedException(string.Format("{0}不支持Request的调用", this.GetType().FullName));
            }
            /// <summary>
            /// 请求数据,根据会话ID发送,
            /// 一般用于并发处理场合,根据ID来确认具体的发送会话,
            /// 用于服务监听应答场合
            /// </summary>
            /// <param name="sessionID">会话ID</param>
            /// <param name="request">请求发送的数据</param>
            public virtual bool Request(string sessionID, TRequest request)
            {
                throw new NotImplementedException(string.Format("{0}不支持Request的调用", this.GetType().FullName));
            }
            /// <summary>
            /// 异步请求数据,在其他线程上
            /// </summary>
            /// <param name="request">请求的数据</param>
            public virtual bool TryASyncRequest(TRequest request,out Exception ex)
            {
                 ex=new Exception(string.Format("{0}不支持ASyncRequest的调用", this.GetType().FullName));
                 return false;
            }
            /// <summary>
            /// 请求广播发送数据
            /// </summary>
            /// <param name="requestData">请求数据</param>
            public virtual void RequestBroadCast(TRequest requestData)
            {
                throw new NotImplementedExcepti

    具体的通信层实现部分:

    /// <summary>
        /// 异步高性能TCP监听服务
        /// </summary>
        /// <typeparam name="TInputMessageFilter">请求消息构建类型</typeparam>
        /// <typeparam name="TOutputMessageFilter">应答消息过滤器类型</typeparam>
        /// <typeparam name="TRequest">请求数据</typeparam>
        /// <typeparam name="TResponse">应答数据</typeparam>
        public class TCPAsyncServerCommunication<TInputMessageFilter, TOutputMessageFilter, TRequest, TResponse>
            : BaseCommunication<TRequest, TResponse>,IDisposable
            where TInputMessageFilter : BaseInPutMessageFilter<TRequest>
            where TOutputMessageFilter : BaseOutPutMessageFilter<TRequest, TResponse>
            where TRequest : BaseRequestData
            where TResponse : BaseResponseData
        {
            /// <summary>
            /// 用于向SocketAsyncEventArgs统一进行内存分配和管理
            /// </summary>
            BufferManager BufferManager;
            /// <summary>
            /// 用于限制最大的连接数量
            /// </summary>
            SemaphoreSlim MaxConnectionsEnforcer;
            /// <summary>
            /// 在同一时刻控制最大并发的发送数量,通过SocketAsyncEventArgs
            /// </summary>
            SemaphoreSlim MaxSaeaSendEnforcer;
            /// <summary>
            /// 在同一时刻控制最大并发的连接数量
            /// </summary>
            SemaphoreSlim MaxAcceptOpsEnforcer;
            /// <summary>
            /// 用于监听进入的连接
            /// </summary>
            Socket ListenSocket;
            /// <summary>
            /// 等待连接栈
            /// </summary>
            SocketAsyncEventArgsPool AcceptPoolEventArgs;
            /// <summary>
            /// 接收数据栈
            /// </summary>
            SocketAsyncEventArgsPool RecivePoolEventArgs;
            /// <summary>
            /// 发送栈
            /// </summary>
            SocketAsyncEventArgsPool SendPoolEventArgs;
            /// <summary>
            /// TCP连接地址
            /// </summary>
            IPEndPoint end;
            /// <summary>
            /// 网络连接的IP地址和端口号
            /// </summary>
            string endPort;
            /// <summary>
            /// 已建立的会话
            /// </summary>
            private Dictionary<string, TCPConnectSession<TRequest, TResponse>> dicConnectSession = new Dictionary<string, TCPConnectSession<TRequest, TResponse>>();
            /// <summary>
            /// 连接处理锁
            /// </summary>
            private object acceptLock = new object();
            /// <summary>
            /// 用于Socket监听的托管队列
            /// </summary>
            private IMessageFIFO acceptFIFO = MessageFIFOFactory.Create(MessageFIFOType.IOCPMessageFIFO);
            /// <summary>
            /// 监听信号量
            /// </summary>
            private ManualResetEvent acceptWaitResetEvent = new ManualResetEvent(false);
            /// <summary>
            /// 通信端口初始化参数
            /// </summary>
            protected TCPAsyncServerParameters communicationParamerters;
            /// <summary>
            /// 发送广播的消息队列
            /// </summary>
            private IMessageFIFO broadCastFIFO = MessageFIFOFactory.Create(MessageFIFOType.IOCPMessageFIFO);
            /// <summary>
            /// 连接模式构造
            /// </summary>
            ///<param name="pa">通信参数</param>
            private TCPAsyncServerCommunication(TCPAsyncServerParameters pa)
            {
                this.communicationParamerters = pa;
                this.end = new IPEndPoint(IPAddress.Parse(pa.Ip), pa.PortNO);
                this.endPort = string.Format("{0}:{1}", pa.Ip, pa.PortNO);
                broadCastFIFO.Excute += broadCastFIFO_Excute;
                acceptFIFO.Excute += acceptFIFO_Exceute;
            }
            /// <summary>
            /// 广播数据处理
            /// </summary>
            /// <param name="obj"></param>
            void broadCastFIFO_Excute(object obj)
            {
                TRequest requestData = null;
                if (obj is TRequest)
                {
                    requestData = (TRequest)obj;
                }
                if (requestData == null)
                {
                    return;
                }
                try
                {
                    List<TCPConnectSession<TRequest, TResponse>> listConnectSession = new List<TCPConnectSession<TRequest, TResponse>>();
                    lock (acceptLock)
                    {
                        if (dicConnectSession.Count > 0)
                        {
                            foreach (var item in dicConnectSession)
                            {

    上述是通信组件的一个具体通信实现的关键类,可以看到把四个变化部分,全部用泛型做了替代,这样就可以实现组件与具体的实现无关性,从而实现反转控制,利用具体的实例化传入参数,进行调度的实例化加载。

    简单的字符串发送广播应用示例:


    请求数据部分

     public class TcpServerTestRequest:Trace.Common.Communication.Request.BaseRequestData
        {
            private string broadCastData;
            /// <summary>
            /// 广播数据
            /// </summary>
            public string BroadCastData
            {
                get 
                {
                    return broadCastData;
                }
                set
                {
                    broadCastData = value;
                }
            }
        }

    应答数据部分

    public class TcpServerTestResponse:Trace.Common.Communication.Response.BaseResponseData
        {
            private string message;
            public string Message
            {
                get 
                {
                    return message;
                }
                set
                {
                    message = value;
                }
            }
        }


    消息输入过滤器:

    public class TcpServerTestInputFilter
            :Trace.Common.Communication.Message.BaseInPutMessageFilter<TcpServerTestRequest>
        {
    
            public override byte[] ProcessToSendBuffer(TcpServerTestRequest requestData)
            {
                return System.Text.Encoding.Default.GetBytes(requestData.BroadCastData);
            }
        }

    消息应答解包过滤器:
     public class TcpServerTestOuptFilter
            :Trace.Common.Communication.Message.BaseOutPutMessageFilter<TcpServerTestRequest,TcpServerTestResponse>
        {
            private IMessageFilterHelper messageFilterHelper = null;
            /// <summary>
            /// 包尾
            /// </summary>
            private byte[] end = new byte[] { 0x0D,0x0A };
            public TcpServerTestOuptFilter()
            {
                messageFilterHelper = new MessageFilterFixEndHelper(end);
            }
            protected override void InputBufferData(string sessionID, byte[] buffer)
            {
                messageFilterHelper.InputBufferData(buffer);
            }
            protected override TcpServerTestResponse GetNextResponse()
            {
                byte[] tempBuffer = messageFilterHelper.GetNextData();
                if (tempBuffer == null || tempBuffer.Length == 0)
                {
                    return null;
                }
                string str=System.Text.Encoding.Default.GetString(tempBuffer);
                TcpServerTestResponse temp = new TcpServerTestResponse();
                temp.Message = str;
                return temp;
            }
        }


    调用实现:                


       /// <summary>
            /// 接收连接
            /// </summary>
            ICommunication<TcpServerTestRequest, TcpServerTestResponse> iReceiveCommunication;
            private void butStart_Click(object sender, EventArgs e)
            {
                SendData sendData = new SendData();
                sendData.SendCommand = SendCommand.Open;
                this.ImessageFIFOInput(sendData);
            }
            private void Start()
            {
                try
                {
                    string ip = this.tB_IP.Text.Trim();
                    int receivePort = Convert.ToInt32(this.tBReceivePort.Text.Trim());
                    BaseCommunicationParameters receivePa = new TCPServerParameters(ip, receivePort);
                    if (iReceiveCommunication == null)
                    {
                        iReceiveCommunication = CommunicationFactory<TcpServerTestInputFilter, TcpServerTestOuptFilter, TcpServerTestRequest, TcpServerTestResponse>.Create(receivePa);
                        iReceiveCommunication.OnResponseBuffer += iReceiveCommunication_OnResponseBuffer;
                        iReceiveCommunication.OnResponseInfo += iReceiveCommunication_OnResponseInfo;
                        iReceiveCommunication.OnOperateStaus += iSendCommunication_OnOperateStaus;
                        iReceiveCommunication.OnSessionAdded += iReceiveCommunication_OnSessionAdded;
                        iReceiveCommunication.OnSessionRemoved += iReceiveCommunication_OnSessionRemoved;
                    }
                    if (iReceiveCommunication.IsOpen == false)
                    {
                        iReceiveCommunication.Open();
                    }
                }
                catch (Exception ex)
                {
                    this.Invoke(new MessShow(ShowMessage),ex.Message);
                    return;
                }
                this.Invoke(new MessShow(ShowMessage), "started");
            }
    
            void iReceiveCommunication_OnSessionRemoved(SessionInfo info)
            {
                this.Invoke(new MessShow(ShowMessage), string.Format("会话ID:{0},远程端口:{1} 主动断开连接,时间:{2}", info.SessionID, info.RemotePort, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")));
    
            }
    
            void iReceiveCommunication_OnSessionAdded(SessionInfo info)
            {
                this.Invoke(new MessShow(ShowMessage), string.Format("会话ID:{0},远程端口:{1}成功建立连接,时间:{2}", info.SessionID,info.RemotePort, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")));
    
            }
    
            void iReceiveCommunication_OnResponseBuffer(object sender, TcpServerTestResponse e)
            {
                this.Invoke(new MessShow(ShowMessage), string.Format("会话ID:{0},接收数据:{1},接收时间:{2}",e.SessionID.ToString(),e.Message,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")));
            }
    
            void iSendCommunication_OnOperateStaus(object sender, OperateStatus e)
            {
                if (e == OperateStatus.Opening)
                {
                    this.Invoke(new MessShow(ShowMessage), "请求启动");
                }
                else if (e == OperateStatus.Opened)
                {
                    this.Invoke(new MessShow(ShowMessage), "启动成功");
                }
                else if (e == OperateStatus.Closing)
                {
                    this.Invoke(new MessShow(ShowMessage), "请求关闭");
                }
                else if (e == OperateStatus.Closed)
                {
                    this.Invoke(new MessShow(ShowMessage), "关闭成功");
                }
            }
    
            void iReceiveCommunication_OnResponseInfo(object sender, ResponseInfo e)
            {
                if (e.ResponseInfoType == ResponseInfoType.NotifyInfo)
                {
                    this.Invoke(new MessShow(ShowMessage), e.Message.Replace("\r\n", ""));
                }
                else if (e.ResponseInfoType == ResponseInfoType.Exception)
                {
                    this.Invoke(new MessShow(ShowMessage), e.Exception.Message.Replace("\r\n", ""));   
                }
                else if (e.ResponseInfoType == ResponseInfoType.ReceiveLog)
                {
                    if (cB_ReceiveLog.Checked == true)
                    {
                        this.Invoke(new MessShow(ShowMessage), e.Message.Replace("\r\n", ""));
                    }
                }
                else if (e.ResponseInfoType == ResponseInfoType.SendLog)
                {
                    if (cB_SendLog.Checked == true)
                    {
                        this.Invoke(new MessShow(ShowMessage), e.Message.Replace("\r\n", ""));
                    }
                }
            }
         
        
            private void butStop_Click(object sender, EventArgs e)
            {
                SendData sendData = new SendData();
                sendData.SendCommand = SendCommand.Close;
                ImessageFIFOInput(sendData);
            }
            private void Stop()
            {
                try
                {
                    if (iReceiveCommunication != null)
                    {
                        if (iReceiveCommunication.IsOpen == true)
                        {
                            iReceiveCommunication.Close();
                        }
                    }
                    this.Invoke(new MessShow(ShowMessage),"stoped");  
                }
                catch (Exception ex)
                {
                    this.Invoke(new MessShow(ShowMessage), ex.Message);  
                }
            }

    因为最复杂的通信和调度部分被封装了,实现部分就简单很多,只需要传入具体的请求类、应答类、输入输出消息过滤器,就可以启动接收和发送数据了。

    2、第一版中基本上已经实现了整个设计部分的功能,但在迁入到项目中时遇到了问题,项目应用中需要对输入和应答,配对反馈回请求端,但是由于设计时就考虑了吞吐性,输入和应答部分,是独立在不同的线程上,如果要操作就需要在全局变量上处理,势必要加入锁机制或队列,这不是一个好的注意,曾经试过很多方式,最终把请求部分合并到应答线程上排队,即发送之前,先进行请求数据的同步处理,让其同步到应答线程上,应答时再合并,整个响应和调度速度比起全局锁处理,效率瞬间提高很多,此处的应答线程不是连接会话的数据回馈线程,连接会话上的数据需要二次在这个线程上同步,因为连接会话由底层线程池发起,其具体的线程是不确定的,无法使用线程池中的线程作为应答线程。还遇到一个问题,是原来的经验或思维定势造成的,在一些与设备交互场合,需要实现一个同步的调用过程,即发送了指令给设备,设备给出答复之后,原调用函数再返回,否则需要等待超时,因为这个机制的引入,一直想着也放在通信的连接会话上去处理,刚开始还没发现问题,后来再大协议块或密集协议块中,发现了这种机制的问题,数据连包或业务层处理超时,都会引起同步函数的不确定性或数据丢包,在考虑了很长一段时间后,意识到应该放入过滤器层,这层因为是面向设备的应用层,才能完整的知道设备动作而不是时间间隔字节流数据。这个地方因为是没有太多可借鉴的,曾经纠结了很长一段时间。

    3、日志完善,随着在项目中更多的设备通信迁移进来,发现在很多时候,尤其是与设备有过多交互时,记录日志是一个很麻烦的事情,因为日志的记录,必定要记下原因,或发起者等,这些信息不能全部传到组件中,既然不能传入,那能不能回调出去,在调用部分之外进行复核,这是引入了跟踪ID,这是借鉴阿里中间团队的一个思路,他们也曾经面临了数据在内存中的快速追踪定位问题,引入跟踪ID之后,就可以实现不论转了多少圈,经过多少调度,还能找到原始起点。这部分曾经引起了组件的一次大变更,也可以说是去组件代码大变更,代码量变小,目的性更明确了。

    4、应用完善,将不同的场合再次分类,抽象。




    展开全文
  • 最全面的UMTS通信协议栈,各种接口,各种接口及相互关系。 通信呼叫详细过程
  • 汽车故障诊断系统通信协议栈,可作为对汽车故障诊断开发指导文档
  • 从协议的分布性和简约性出发 ,设计了适用于当前大多数无线传感器网络节点平台的嵌入式协议栈 ,使节点快速地自组织构建网络并且实现数据通信协议栈采用了多种路由和组网方式 ,直接为应用提供网络通信接口。仿真...
  • 最新官网MySQL通信协议栈说明地址:http://dev.mysql.com/doc/internals/en/client-server-protocol.html 1. 数据类型 1.1 整型 1.1.1 定长整型 定长整型最小位在最前,一共有如下几种定长整型: ...

    最新官网MySQL通信协议栈说明地址:http://dev.mysql.com/doc/internals/en/client-server-protocol.html

    1. 数据类型

    1.1 整型

    1.1.1 定长整型

    定长整型最小位在最前,一共有如下几种定长整型:

    int<1>
    int<2>
    int<3>
    int<4>
    int<6>
    int<8>

    例如:int<3>表示1为:

    01 00 00

    1.1.2 长度编码整型

    int<lenenc>

    根据长度不同,长度编码整型有不同的编码:
    如果值<251,则存储为1字节整型
    如果值≥251并<2^16,则存储为以0xfc开头+2字节整型
    如果值≥2^16并<2^24,则存储为以0xfd开头+3字节整型
    如果值≥2^24并<2^64,则存储为以0xfe开头+8字节整型
    举例:

    fa       -- 250
    fc fb 00 -- 251

    1.1.3 实现

    Int.java:

    package io.timberwolf.net.protocols.mysql.data;
    
    import com.google.common.base.Preconditions;
    
    import java.nio.ByteBuffer;
    
    /** * MySQL protocol DataType - Integer Types * * @author Hash Zhang * @version 0.0.0 * @see @http://dev.mysql.com/doc/internals/en/integer.html */
    public class Int {
        //定长整型数据编码解码
        public static int writeLength1(ByteBuffer buffer, int num) {
            Preconditions.checkArgument(num < 0x100);
            buffer.put((byte) num);
            return 1;
        }
    
        public static int readLength1(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            return (int) buffer.get();
        }
    
        public static int writeLength2(ByteBuffer buffer, int num) {
            Preconditions.checkArgument(num < 0x10000);
            buffer.put((byte) (num));
            buffer.put((byte) (num >>> 8));
            return 2;
        }
    
        public static int readLength2(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            int result = (int) buffer.get();
            result += ((int) buffer.get()) << 8;
            return result;
        }
    
        public static int writeLength3(ByteBuffer buffer, int num) {
            Preconditions.checkArgument(num < 0x1000000);
            buffer.put((byte) (num));
            buffer.put((byte) (num >>> 8));
            buffer.put((byte) (num >>> 16));
            return 3;
        }
    
        public static int readLength3(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            int result = (int) buffer.get();
            result += ((int) buffer.get()) << 8;
            result += ((int) buffer.get()) << 16;
            return result;
        }
    
        public static int writeLength4(ByteBuffer buffer, long num) {
            Preconditions.checkArgument(num < 0x100000000L);
            buffer.put((byte) (num));
            buffer.put((byte) (num >>> 8));
            buffer.put((byte) (num >>> 16));
            buffer.put((byte) (num >>> 24));
            return 4;
        }
    
        public static long readLength4(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            long result = (long) buffer.get();
            result += ((long) buffer.get()) << 8;
            result += ((long) buffer.get()) << 16;
            result += ((long) buffer.get()) << 24;
            return result;
        }
    
        public static int wrietLength6(ByteBuffer buffer, long num) {
            Preconditions.checkArgument(num <= 0x1000000000000L);
            buffer.put((byte) (num));
            buffer.put((byte) (num >>> 8));
            buffer.put((byte) (num >>> 16));
            buffer.put((byte) (num >>> 24));
            buffer.put((byte) (num >>> 32));
            buffer.put((byte) (num >>> 40));
            return 6;
        }
    
        public static long readLength6(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            long result = (long) buffer.get();
            result += ((long) buffer.get()) << 8;
            result += ((long) buffer.get()) << 16;
            result += ((long) buffer.get()) << 24;
            result += ((long) buffer.get()) << 32;
            result += ((long) buffer.get()) << 40;
            return result;
        }
    
        public static int writeLength8(ByteBuffer buffer, long num) {
            buffer.put((byte) num);
            buffer.put((byte) (num >>> 8));
            buffer.put((byte) (num >>> 16));
            buffer.put((byte) (num >>> 24));
            buffer.put((byte) (num >>> 32));
            buffer.put((byte) (num >>> 40));
            buffer.put((byte) (num >>> 48));
            buffer.put((byte) (num >>> 56));
            return 8;
        }
    
        public static long readLength8(ByteBuffer buffer) {
            Preconditions.checkNotNull(buffer);
            long result = (long) buffer.get();
            result += ((long) buffer.get()) << 8;
            result += ((long) buffer.get()) << 16;
            result += ((long) buffer.get()) << 24;
            result += ((long) buffer.get()) << 32;
            result += ((long) buffer.get()) << 40;
            result += ((long) buffer.get()) << 48;
            result += ((long) buffer.get()) << 56;
            return result;
        }
    
        //长度编码整型数据编码解码
        public static int writeLengthEncoded(ByteBuffer buffer, long num) {
            if (num < 0xfb) {
                writeLength1(buffer, (int) num);
                return 1;
            } else if (num < 0x10000) {
                buffer.put((byte) 0xfc);
                writeLength2(buffer, (int) num);
                return 3;
            } else if (num < 0x10000) {
                buffer.put((byte) 0xfd);
                writeLength3(buffer, (int) num);
                return 4;
            } else {
                buffer.put((byte) 0xfe);
                writeLength8(buffer, num);
                return 9;
            }
        }
    
        public static long readLengthEncoded(ByteBuffer buffer) {
            int num = readLength1(buffer);
            long result = 0;
            if(num < 0xfb){
                result += num;
            } else if(num == 0xfc){
                result += readLength2(buffer);
            } else if(num == 0xfd){
                result += readLength3(buffer);
            } else{
                result +=readLength8(buffer);
            }
            return result;
        }
    }
    
    
    

    1.2 字符串类型

    1.2.1定长字符串

    定长字符串拥有已知的固定的长度

    1.2.2null截止字符串

    字符串用[00]字节截止

    1.2.3变长字符串

    字符串长度由另一域值决定

    1.2.4长度编码字符串

    长度编码整型+定长字符串(长度为前面整型代表的数值)

    1.2.5剩余长度字符串

    如果字符串是包最后一个元素,它的长度可以由包长度减去当前位置决定。

    string<lenenc>  Protocol::LengthEncodedString
    string<fix> Protocol::FixedLengthString
    string<var> Protocol::VariableLengthString:
    string<EOF> Protocol::RestOfPacketString
    string<NUL> Protocol::NulTerminatedString
    package io.timberwolf.net.protocols.mysql.data;
    
    import com.google.common.base.Preconditions;
    
    import java.io.UnsupportedEncodingException;
    import java.nio.ByteBuffer;
    
    /** * MySQL protocol DataType - String Types * * @author Hash Zhang * @version 0.0.0 * @see @http://dev.mysql.com/doc/internals/en/string.html */
    public class Str {
        public static int lengthEncoded(ByteBuffer buffer, String string, String charSet) throws UnsupportedEncodingException {
            Preconditions.checkNotNull(string);
            int length = string.getBytes(charSet).length;
            length += Int.writeLengthEncoded(buffer,length);
            buffer.put(string.getBytes(charSet));
            return length;
        }
    }
    
    

    转载于:https://my.oschina.net/zhxdick/blog/665219

    展开全文
  • 有没有人有WCDMA通信协议栈的RRC层、RLC层和MAC层大C语言代码,因为现在要在虚拟机上实现上层的通信协议,模拟上层信号的处理过程
  • 2. 协议包格式 MySQL client和MySQL server之间要想传输数据,必须: 1. 将数据切分成若干个大小不超过字节(16MB)的packet里面 2. 将每一个数据包封装一个包头 2.1. 数据包结构 Type Na...
  • 本文介绍了ZigBee技术及其协议栈的结构,并针对该协议栈中的内存管理和时间管理技术为ZigBee协议栈的设计了内存分类管理办法和基于时钟队列的软定时器模型,测试表明,该设计方法能够有效的提高ZIGEE协议栈稳定性和...
  • zigBee是一种新兴的短距离、低速率无线网络技术,文章介绍了zigBee技术及其协议栈的结构,针对协议栈中的内存管理和时间管理技术分别设计了内存分类管理模型和基于时钟队列的软定时器模型,并在chipcon公司出产的cc...
  • 文章目录菜狗的网安学习路线笔记——网络基础(一)前言一、OSI七层协议模型1.七层结构2.各层功能定义<1> 应用层<2> 表示层<3> 会话层<4> 传输层<5> 网络层<6> 数据链路层<7...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,576
精华内容 1,830
关键字:

通信协议栈