一种实现路由器中业务与协议栈之间数据交互的方法
技术领域
本发明涉及通信领域,具体涉及一种实现路由器中业务与协议栈之间数据交互的方法。
背景技术
目前,路由器平台主要是基于模块化思想,以组件作为最基本的功能单元;一个功能的实现往往需要多个组件之间的交互,业务模块与收发包模块(NIO组件,NetworkInput&Output,高性能收发包组件)分属于不同的组件,统一负责业务数据消息的封装与收发,目前业务组件与NIO组件的协议栈之间数据交互使用同步式的SOCKET,业务组件需要很长时间来等待数据发送成功返回消息,影响业务的处理性能,况且没有统一的编程接口,每种业务都需要选择跨进程间消息,代码冗余利用率也不高。
综上所述,亟需一种实现路由器业务与协议栈之间数据交互的新方案,来提高业务处理性能。
发明内容
本发明所要解决的技术问题是目前业务组件与NIO组件的协议栈之间数据交互使用同步式的SOCKET,业务组件需要很长时间的等待数据发送成功返回消息,业务的处理性能低,且没有统一的编程接口,每种业务都需要选择跨进程间消息,代码冗余利用率也不高的问题。
为了解决上述技术问题,本发明所采用的技术方案是提供一种实现路由器中业务与协议栈之间数据交互的方法,包括:
步骤S10、业务组件在其与NIO组件之间创建一个SOCKET,并在创建SOCKET时在SOCKET LIB端注册一个返回事件的回调函数,构建异步SOCKET;
其中,返回事件的回调函数包含对不同类型的回应消息进行处理的处理函数;
步骤S20、业务组件调用SOCKET LIB端接口进行数据收发,且每次无需等待NIO组件处理结果,立即返回,直接进行下一条数据消息的处理;
步骤S30、NIO组件处理完成后,生成一条携带处理结果的回应消息,并调用返回事件的回调函数通知对应业务组件。
在上述方法中,SOCKET LIB端与NIO组件间的通信采用PCS和共享内存两种方式;
在业务量不大时,业务组件的SOCKET LIB端与NIO组件之间的通信只使用PCS;
在业务量较大时,业务组件的SOCKET LIB端与NIO组件之间的控制消息通过PCS实现交互通信;业务组件的SOCKET LIB端与NIO组件之间的数据报文通过共享内存实现交互通信。
在上述方法中,在业务量较大时,业务组件的SOCKET LIB端与NIO组件之间的数据报文通过共享内存实现交互通信,需要在SOCKET创建时,以业务组件为单位申请共享内存;
业务组件在SOCKET创建时,通过设置用于判断是否采用共享内存存取数据报文的共享内存标记位,请求NIO组件申请共享内存;NIO组件在SOCKET创建成功后申请共享内存,并映射该共享内存,并将共享内存ID返回给对应业务组件,业务组件根据此共享内存ID同样将对应共享内存映射到本地;
其中,所述共享内存包括接收、发送两块共享内存。
在上述方法中,同一业务组件只第一个SOCKET申请共享内存。
在上述方法中,在业务组件的SOCKET LIB端与NIO组件之间的数据报文通过共享内存来实现消息通信时,采用从无到有消息通知的机制,具体为:
在发送方向,当SOCKET LIB端发送一个业务数据报文时,先判断发送共享内存队列是否为空,如果为空,在将数据报文存入发送共享内存的同时发送一个通知消息到NIO组件,NIO组件接收到通知消息后,开始依次读取发送共享内存中数据报文,直至将发送共享内存队列读空;如果非空,不发送通知消息,直接将数据报文存入发送共享内存;
在接收方向,当NIO组件接收到业务数据报文时,先判断接收共享内存队列是否为空,如果为空,将数据报文存入接收共享内存,并同时发送一个通知消息到SOCKET LIB端,SOCKET LIB端收到通知消息后,连续读取接收共享内存中的数据报文,上送到业务组件,直到接收共享内存队列为空;如果非空,不发送通知消息,直接将数据报文存入接收共享内存。
在上述方法中,在共享内存的读出端设有定时扫描机制;
所述定时扫描机制为:
在发送共享内存和接收共享内存的读出端设置循环定时器;
定时器超时,直接扫描对应的发送共享内存或接收共享内存;如果发送共享内存或接收共享内存队列不为空,则将其中数据报文全部读出。
在上述方法中,步骤S10具体包括以下步骤:
步骤S101、业务组件调用SOCKET LIB端接口创建一个套接字SOCKET,并在创建SOCKET时注册一个返回事件的回调函数;
步骤S102、业务组件在SOCKET LIB端为SOCKET分配一个在该业务组件上唯一的SOCKET资源,包括在SOCKET LIB端唯一的标识符appfd及关联的数据结构体;
步骤S103、将业务组件的返回事件的回调函数绑定到SOCKET资源的数据结构体中;
步骤S104、在SOCKET LIB端构建SOCKET创建消息的结构体,发送给NIO组件;其中,结构体携带域参数domain、SOCKET类型type、协议参数protocol和在业务组件上的SOCKET资源的标识符appfd信息;
步骤S105、NIO组件收到SOCKET LIB端发送过来的消息,在NIO组件上分配一个全局唯一SOCKET资源给该业务组件对应的SOCKET;
步骤S106、NIO组件调用NIO组件内部函数创建SOCKET,获得SOCKET指针,并建立SOCKET指针与在NIO组件上对应SOCKET资源的标识符niofd的映射关系;
步骤S107、判断在NIO组件创建SOCKET是否成功,如果创建成功,执行步骤S108;否则,执行步骤S109;
步骤S108、创建“NIO组件创建SOCKET成功”事件的消息结构体,并携带在NIO组件上的SOCKET资源的标识符niofd、在业务组件上的SOCKET资源的标识符appfd信息,发送给对应业务组件的SOCKET LIB端,然后执行步骤S110;
步骤S109、NIO组件释放相应资源,创建“NIO组件创建SOCKET失败”事件的消息结构体,并携带在业务组件上的SOCKET资源的标识符appfd信息和错误类型码信息,发送给对应业务组件的SOCKET LIB端,然后执行步骤S110;
步骤S110、SOCKET LIB端收到NIO组件发送的消息,并进行解析,判断该消息是否为“NIO组件创建SOCKET成功”事件,如果是,执行步骤S112;否则,执行步骤S111;
步骤S111、根据在业务组件上的SOCKET资源的标识符appfd信息,直接调用业务组件注册的返回事件的回调函数通知对应业务组件;
步骤S112、获取消息中携带的在NIO组件上SOCKET资源的标识符niofd和在业务组件上的SOCKET资源的标识符appfd,并建立、维护两者之间的映射关系,再根据在业务组件上的SOCKET资源的标识符appfd信息调用业务组件注册的返回事件的回调函数通知对应业务组件。
在上述方法中,在SOCKET创建时,以业务组件为单位申请共享内存,具体包括如下步骤:
步骤S401、业务组件在创建SOCKET时,设置用于判断是否采用共享内存存取数据报文的内存共享标记位,并添加到SOCKET创建消息中,发送给NIO组件;
步骤S402、NIO组件在SOCKET创建成功后,判断是否收到带有内存共享标记位的消息,如果没有,直接向SOCKET LIB端发送“NIO组件创建SOCKET成功”消息;否则,执行步骤S403;
步骤S403、NIO组件打开一块共享内存,生成对应的共享内存ID,并将该共享内存映射到本地;
步骤S404、为共享内存创建一个共享内存队列,并初始化;
步骤S405、将共享内存ID添加到“NIO组件创建SOCKET成功”消息中发送给SOCKETLIB端;
步骤S406、SOCKET LIB端收到“NIO组件创建SOCKET成功”消息,建立、维护在NIO组件上SOCKET资源的标识符niofd和在业务组件上的SOCKET资源的标识符appfd之间的映射关系;
步骤S407、判断“NIO组件创建SOCKET成功”是否携带共享内存ID,如果有,执行步骤S408;否则,调用业务组件注册的返回事件的回调函数通知事件结果;
步骤S408、SOCKET LIB端根据共享内存ID打开共享内存,并映射到本地,并调用业务组件注册的返回事件的回调函数通知事件结果。
在上述方法中,SOCKET LIB端发送数据报文,具体包括以下步骤:
步骤S11、业务组件调用发包接口函数,根据业务组件指定的数据传输类型在SOCKET LIB端判断是否使用共享内存;如果使用,执行步骤S12;否则,用PCS直接发送给NIO组件;
步骤S12、抛出信号量等待,并获取发送共享内存队列是否为空的标记,申请发送共享内存保存待发送业务数据报文;
步骤S13、判断发送共享内存队列是否标记为空,如果为空,执行步骤S14;否则,执行步骤S15;
步骤S14、将数据报文存入发送共享内存队列,并发送通知消息给NIO组件,告知NIO组件开始读取发送共享内存中数据,直到发送共享内存为空;
步骤S15、将数据报文存入发送共享内存队列。
在上述方法中,SOCKET LIB端接收数据报文,具体包括以下步骤:
步骤S21、SOCKET LIB端接收到NIO组件发送的开始读取数据报文的通知消息后,根据数据传输类型判断是否使用接收共享内存;如果使用,执行步骤S22;否则,直接调用业务回调;
步骤S22、抛出信号量等待,并获取接收共享内存队列的头结点;
步骤S23、判断接收共享内存队列的头结点是否为空,如果不为空,则执行步骤S24;否则,执行步骤S22;
步骤S24、读取接收共享内存头结点中数据报文,并置标记位为有数据到达类型,主动调用注册的返回事件的回调函数,将数据通知给业务组件;
步骤S25、释放当前头结点对应位置的共享内存,并将该头结点从接收共享内存队列中摘除,然后执行步骤S22。
本发明采用异步SOCKET调用来实现消息的通知,并实现了一种回调函数注册的处理机制,使得业务无需等待对方执行完毕才返回,只需要通过调用注册的回调函数,来通知业务组件数据到达,实现业务组件的数据处理和I/O操作重叠进行,有效解决了同步阻塞问题,实现业务组件的数据处理和SOCKET操作重叠进行,且通过使用共享内存进行进程间通信进一步提升了系统的性能。
附图说明
图1为本发明提供的一种实现路由器中业务与协议栈之间数据交互的方法的流程图;
图2为本发明中步骤S10的具体流程图;
图3为本发明中业务组件的SOCKET LIB端与NIO组件之间通过共享内存进行消息通信的流程图;
图4为本发明中SOCKET LIB端发送数据处理的流程图;
图5为本发明中SOCKET LIB端接收数据处理的流程图。
具体实施方式
本发明NIO组件采用异步式SOCKET,实现业务收发数据的异步操作,减少进程间的相互等待,提高业务处理性能,且NIO组件提供一套完整的API给业务使用,这套API以LIB(动态链接库)的形式驻留在业务组件中,而SOCKET创建及共享内存的实现都是编程接口一部分,均是由业务通过该LIB实现,可见LIB统一了编程接口。
下面结合说明书附图和具体实施例对本发明做出详细的说明。
如图1所示,本发明提供了一种实现路由器中业务与协议栈之间数据交互的方法,包括:
步骤S10、业务组件调用SOCKET LIB端接口在业务组件与NIO组件之间创建一个SOCKET(套接字),用于业务组件与NIO组件的协议栈之间进行数据交互,并在创建SOCKET时在SOCKET LIB端注册一个返回事件的回调函数,构建异步SOCKET,其中,返回事件的回调函数包含对不同类型的回应消息进行处理的处理函数(业务组件不关心的结果也可不处理);
步骤S20、业务组件调用SOCKET LIB端接口进行数据收发,且每次无需等待NIO组件处理结果,立即返回,直接进行下一条数据消息的处理;
步骤S30、NIO组件处理完成后,生成一条携带处理结果的回应消息,并调用返回事件的回调函数通知对应业务组件;返回事件的回调函数根据回应消息的类型选择该类型回应消息对应的处理函数,对回应消息进行处理,并发送到对应业务组件。在本发明中,SOCKET采用异步编程思想,因此必须在得到上一步操作(步骤S20)成功的回调信号之后,才能执行下一步操作(步骤S30)。
由于性能对于收发包模块来说至关重要,有大量的数据需要收发时,仅通过TIPC(Transparent Inter-process Communication,透明进程间通信)封装的可靠消息还是有一定的性能瓶颈,所以本发明在业务量较大时,SOCKET LIB端与NIO组件间的通信采用两种方式,控制消息采用PCS(Point to Point Communication Service,点到点通信服务:在两个组件之间发送点到点消息,提供可靠的消息发送;为TIPC封装),数据报文采用共享内存的方式,这样极大的提高了系统的吞吐量以及系统的性能。在业务量较大时,业务组件的SOCKET LIB端与NIO组件之间的数据报文通过共享内存来实现消息通信,需要在SOCKET创建时,以业务组件为单位申请共享内存,业务组件在SOCKET创建时,通过设置用于判断是否采用共享内存存取数据报文的共享内存标记位,请求NIO组件申请共享内存;NIO组件在SOCKET创建成功后申请共享内存,并映射该共享内存,并将共享内存ID返回给对应业务组件,业务组件根据此ID同样将对应共享内存映射到本地,其中,
同一业务组件只第一个SOCKET申请共享内存;
共享内存包括接收、发送两块共享内存。
为了在业务量比较大时能够极大的减少SOCKET LIB端与NIO组件之间通知消息的交互,在业务组件的SOCKET LIB端与NIO组件之间的数据报文通过共享内存来实现消息通信时,采用从无到有消息通知的机制,具体为:
在发送方向,当SOCKET LIB端发送一个业务数据报文时,先判断发送共享内存队列是否为空,如果为空,在将数据报文存入发送共享内存的同时发送一个通知消息到NIO组件,NIO组件接收到通知消息后,开始依次读取发送共享内存中数据报文,直至将发送共享内存队列读空;如果非空,不发送通知消息,直接将数据报文存入发送共享内存,以为之前已经向NIO组件发送过通知消息了,防止通知消息过多。
在接收方向,当NIO组件接收到业务数据报文时,先判断接收共享内存队列是否为空,如果为空,将数据报文存入接收共享内存,并同时发送一个通知消息到SOCKET LIB端,SOCKET LIB端收到通知消息后,连续读取接收共享内存中的数据报文,上送到业务组件,直到接收共享内存队列为空;如果非空,不发送通知消息,直接将数据报文存入接收共享内存。
本发明还设有定时扫描机制,即在发送共享内存和接收共享内存的读出端设置循环定时器,定时器超时,直接扫描对应的发送共享内存或接收共享内存,如果发送共享内存或接收共享内存队列不为空(存有数据报文),则将其中数据报文全部读出,防止共享内存中积压大量数据报文,或者出现共享内存中数据报文由于某种异常一直无法读出的情况。
在本发明中如图2所示,步骤S10具体包括以下步骤:
步骤S101、业务组件调用SOCKET LIB端接口创建一个套接字SOCKET,并在创建SOCKET时注册一个返回事件的回调函数;
步骤S102、业务组件在SOCKET LIB端为SOCKET分配一个在该业务组件上唯一的SOCKET资源(包括在SOCKET LIB端唯一标识符appfd及关联的数据结构体);
步骤S103、将业务组件的返回事件的回调函数绑定到SOCKET资源数据结构体中;
步骤S104、构建SOCKET LIB端与NIO组件间互相通信的SOCKET创建消息的结构体(PCS),发送给NIO组件,其中,消息的结构体携带domain(域参数)、type(SOCKET类型)、protocol(协议参数)和在业务组件上的SOCKET资源的标识符appfd信息;
步骤S105、NIO组件收到SOCKET LIB端发送过来的消息,在NIO组件上分配一个全局唯一SOCKET资源(因为协议栈可以承载多个业务组件)给该业务组件对应的SOCKET;
步骤S106、NIO组件调用NIO组件内部函数创建SOCKET,获得SOCKET指针,并建立SOCKET指针与在NIO组件上对应SOCKET资源的标识符niofd的映射关系;
步骤S107、判断在NIO组件创建SOCKET是否成功,如果创建成功,执行步骤S108;否则,执行步骤S109;
步骤S108、创建“NIO组件创建SOCKET成功”事件的消息结构体,并携带在NIO组件上的SOCKET资源的标识符niofd、在业务组件上的SOCKET资源的标识符appfd信息,发送给对应业务组件的SOCKET LIB端,然后执行步骤S110;
步骤S109、NIO组件释放相应资源,创建“NIO组件创建SOCKET失败”事件的消息结构体,并携带在业务组件上的SOCKET资源的标识符appfd信息和错误类型码信息,发送给对应业务组件的SOCKET LIB端,然后执行步骤S110;
步骤S110、SOCKET LIB端收到NIO组件发送的消息,并进行解析,判断该消息是否为“NIO组件创建SOCKET成功”事件,如果是,执行步骤S112;否则,执行步骤S111;
步骤S111、根据在业务组件上的SOCKET资源的标识符appfd信息,直接调用业务组件注册的返回事件的回调函数通知对应业务组件;
步骤S112、获取消息中携带的在NIO组件上SOCKET资源的标识符niofd和在业务组件上的SOCKET资源的标识符appfd,并建立、维护两者之间的映射关系,再根据在业务组件上的SOCKET资源的标识符appfd信息调用业务组件注册的返回事件的回调函数中通知对应业务组件。
如图3所示,在SOCKET创建时,以业务组件为单位申请共享内存,具体包括如下步骤:
步骤S401、业务组件在创建SOCKET时,设置用于判断是否采用共享内存存取数据报文的内存共享标记位,并添加到SOCKET创建消息中,发送给NIO组件;
步骤S402、NIO组件在SOCKET创建成功后,判断是否收到带有内存共享标记位的消息,如果没有,直接向SOCKET LIB端发送“NIO组件创建SOCKET成功”消息;否则,执行步骤S403;
步骤S403、NIO组件打开一块共享内存,生成对应的共享内存ID,并将该共享内存映射到本地;
步骤S404、为共享内存创建一个共享内存队列,并初始化;
步骤S405、将共享内存ID添加到“NIO组件创建SOCKET成功”消息中,发送给SOCKETLIB端;
步骤S406、SOCKET LIB端收到“NIO组件创建SOCKET成功”消息,建立、维护在NIO组件上SOCKET资源的标识符niofd和在业务组件上的SOCKET资源的标识符appfd之间的映射关系;
步骤S407、判断“NIO组件创建SOCKET成功”是否携带共享内存ID,如果有,执行步骤S408;否则,调用业务组件注册的返回事件的回调函数通知事件结果(仅仅是创建SOCKET成功);
步骤S408、SOCKET LIB端根据共享内存ID打开共享内存,并映射到本地,并调用业务组件注册的返回事件的回调函数通知事件结果(创建SOCKET成功和共享内存申请成功)。
下面对在采用共享内存时本发明的SOCKET LIB端数据报文处理流程进行详细说明。
如图4所示,SOCKET LIB端发送数据报文处理流程具体包括以下步骤:
步骤S11、业务组件调用发包接口函数,根据业务组件指定的数据传输类型在SOCKET LIB端判断是否使用共享内存;如果使用,执行步骤S12;否则,用PCS直接发送给NIO组件;
步骤S12、抛出信号量等待,并获取发送共享内存队列是否为空的标记,申请发送共享内存保存待发送业务数据报文;
步骤S13、判断发送共享内存队列是否标记为空,如果为空,执行步骤S14;否则,执行步骤S15;
步骤S14、将数据报文存入发送共享内存队列,并发送PCS消息给NIO组件,告知NIO组件开始读取发送共享内存中数据,直到共享内存为空;
步骤S15、将数据报文存入发送共享内存队列。
如图5所示,SOCKET LIB端接收数据报文处理流程具体包括以下步骤:
步骤S21、SOCKET LIB端接收到NIO组件发送的开始读取数据报文的通知消息后,根据数据传输类型判断是否使用接收共享内存;如果使用,执行步骤S22;否则,直接调用业务回调;
步骤S22、抛出信号量等待,并获取接收共享内存队列的头结点;
步骤S23、判断接收共享内存队列的头结点是否为空,如果不为空,则执行步骤S24;否则,继续等待写入,执行步骤S22;
步骤S24、读取接收共享内存头结点中数据报文,并置标记位为有数据到达类型,主动调用注册的返回事件的回调函数,将数据通知给业务组件;
步骤S25、释放当前头结点对应位置的共享内存,并将该头结点从接收共享内存队列中摘除,然后执行步骤S22。
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。