一种基于大型通信系统的消息分发机制的制作方法

文档序号:24065496发布日期:2021-02-26 12:51阅读:178来源:国知局
一种基于大型通信系统的消息分发机制的制作方法

[0001]
本发明涉及通信技术领域,尤其是涉及一种基于大型通信系统的消息分发机制。


背景技术:

[0002]
目前,大型通信系统软件包含大量以进程为载体的二三层通信协议,协议间有状态依赖、时间先后顺序依赖,多个协议可能共享某个系统状态属性,要求大型通信系统软件可以提供满足上述场景的通信模型。
[0003]
进程间通信方式包含有管道、消息队列、信号、信号量、共享内存和套接字,这些方式单一使用不能全面满足大型通信软件系统通信的需求,综合使用过于烦杂且紧耦合不便系统日常维护更新。
[0004]
管道、消息队列、信号、信号量、共享内存和套接字是操作系统提供给用户进行进程间通信的方法。
[0005]
假设协议a由进程a维护,协议b由进程b维护,协议c由进程c维护。现要求协议a和协议b可以相互通信且消息长度和消息量变化范围大,协议a定时询问协议c状态。
[0006]
若使用命名管道实现上述场景进程间通信,虽然克服了进程间同源性的限制,但它仍然是半双工的工作方式,双工的通信方式必须使用两个管道,一个用来发送数据,另一个用来接收。上述场景至少需要四个管道,倘若相互通信的协议增加,管道也会成倍的增加,导致系统资源消耗严重,不符合大型通信软件系统对节约使用系统资源的要求。
[0007]
若使用消息队列实现上述场景进程间通信,因为系统中所有消息队列所包含的全部数据块的总长度有一个上限,所以不符合大型通信软件系统协议可扩展性要求。
[0008]
信号和信号量携带数据量太小,不能满足上述携带大量消息数据的场景,不符合大型通信软件系统消息范围变化大的要求。
[0009]
共享内存的分配是以页大小为单位的,即使通信数据量就几个字节,也必须分配一个4k大小的内存,内存浪费大;而且共享内存不支持数据同步,需要协议本身用信号量等手段进行同步,增加了使用的复杂度。不符合大型通信软件系统节约资源和易扩展的要求。
[0010]
套接字可以实现上述场景,但是没有将各种通信模型进行抽象实现形成统一编程的接口,导致不同开发者以不同的方式实现各通信场景,增加了使用的复杂度,不符合大型通信软件系统易扩展的要求。
[0011]
公开于该背景技术部分的信息仅仅旨在加深对本发明的总体背景技术的理解,而不应当被视为承认或以任何形式暗示该信息构成已为本领域技术人员所公知的现有技术。


技术实现要素:

[0012]
本发明的目的在于提供一种基于大型通信系统的消息分发机制,以解决现有技术中存在的技术问题。
[0013]
为了实现上述目的,本发明采用以下技术方案:
[0014]
本发明提供一种基于大型通信系统的消息分发机制,其包括类linux操作系统套
接字的操作接口、协议模型、传输方式、事件驱动的状态机;其中,
[0015]
类linux操作系统套接字的操作接口,包含创建/关闭模型的nn_socket()/nn_close()接口,设置/获取模型参数的nn_setsocketopt()/nn_getsocketopt()接口,绑定模型地址nn_bind()接口,连接模型nn_connect()的接口,发送/接收模型数据nn_send()/nn_recv()的接口;
[0016]
协议模型,包含一对一全双工pair模型,一对一请求/回复模型,一对多半双工广播发布/订阅模型,一对多询问/确认模型;
[0017]
传输方式,根据通信的方式,将传输方式分为本设备内通信的进程间通信和设备间通信的tcp通信;
[0018]
事件驱动的状态机,将消息分发库的实现分层,每层以状态机的方式运行,通过事件的方式激励状态机。
[0019]
作为一种优选的技术方案:类linux操作系统套接字的操作接口,地址也类linux操作系统地址,采用“传输类型+//:+实际地址”的方式,举例如下,若是进程间通信,则为“ipc//:test”;若是进程间通信,则为“tcp//:192.168.1.10:3000”。
[0020]
作为一种优选的技术方案,该基于大型通信系统的消息分发机制使用pair模型,其包含下面的步骤:
[0021]
步骤1:一端a调用nn_socket()接口创建消息分发库的套接字;
[0022]
步骤2:一端a调用nn_bind()接口绑定地址;
[0023]
步骤3:一端a调用nn_send()发送数据到对端b,此时对端b的消息分发库的套接字还没有创建;
[0024]
步骤4:对端b调用nn_socket()接口创建消息分发库的套接字;
[0025]
步骤5:对端b调用nn_connect()接口连接一端a绑定的地址;
[0026]
步骤6:对端b调用nn_recv()接口接收数据;
[0027]
步骤7:对端b调用nn_send()接口发送数据;
[0028]
步骤8:一端a调用nn_recv()接口接收数据;
[0029]
步骤9:一端a调用nn_close()接口关闭消息分发库的套接字;
[0030]
步骤10:对端b调用nn_close()接口关闭消息分发库的套接字。
[0031]
作为一种优选的技术方案,该基于大型通信系统的消息分发机制使用请求/回复模型,其包含下面的步骤:
[0032]
步骤1:rep_a端调用nn_socket()接口创建消息分发库的套接字;
[0033]
步骤2:rep_a端调用nn_bind()接口绑定地址;
[0034]
步骤3:req_b端调用nn_socket()接口创建消息分发库的套接字;
[0035]
步骤4:req_b端调用nn_connect()接口连接到rep_a端绑定的地址;
[0036]
步骤5:req_c端调用nn_socket()接口创建消息分发库的套接字;
[0037]
步骤6:req_c端调用nn_connect()接口连接到rep_a端绑定的地址;
[0038]
步骤7:req_c端调用nn_send()发送数据到rep_a端;
[0039]
步骤8:req_b端调用nn_send()发送数据到rep_a端;
[0040]
步骤9:rep_a端调用nn_recv()接口接收数据,可以接收req_c端和req_b端发送的数据;
[0041]
步骤10:rep_a端调用nn_send()接口发送数据;
[0042]
步骤11:req_b端调用nn_recv()接口接收数据;
[0043]
步骤12:req_c端调用nn_recv()接口接收数据;
[0044]
步骤13:req_c端调用nn_close()接口关闭消息分发库的套接字;
[0045]
步骤14:req_b端调用nn_close()接口关闭消息分发库的套接字;
[0046]
步骤15:rep_a端调用nn_close()接口关闭消息分发库的套接字。
[0047]
作为一种优选的技术方案,该基于大型通信系统的消息分发机制使用发布/订阅模型,其包含下面的步骤:
[0048]
步骤1:pub_a端调用nn_socket()接口创建消息分发库的套接字;
[0049]
步骤2:pub_a端调用nn_bind()接口绑定地址;
[0050]
步骤3:sub_b端调用nn_socket()接口创建消息分发库的套接字;
[0051]
步骤4:sub_b端调用nn_connect()接口连接到pub_a端绑定的地址;
[0052]
步骤5:sub_c端调用nn_socket()接口创建消息分发库的套接字;
[0053]
步骤6:sub_c端调用nn_connect()接口连接到rep_a端绑定的地址;
[0054]
步骤7:pub_a端调用nn_send()发送数据;
[0055]
步骤8:sub_c端调用nn_recv()接收数据,无数据;
[0056]
步骤9:sub_b端调用nn_recv()接收数据,无数据;
[0057]
步骤10:pub_a端调用nn_send()接口发送数据;
[0058]
步骤11:sub_c端调用nn_recv()接收数据,收到pub_a端发来的数据;
[0059]
步骤12:sub_b端调用nn_recv()接收数据,收到pub_a端发来的数据;
[0060]
步骤13:sub_c端调用nn_close()接口关闭消息分发库的套接字;
[0061]
步骤14:sub_b端调用nn_close()接口关闭消息分发库的套接字;
[0062]
步骤15:pub_a端调用nn_close()接口关闭消息分发库的套接字。
[0063]
作为一种优选的技术方案,该基于大型通信系统的消息分发机制使用询问/确认模型,其包含下面的步骤:
[0064]
步骤1:surv_a端调用nn_socket()接口创建消息分发库的套接字;
[0065]
步骤2:surv_a端调用nn_bind()接口绑定地址;
[0066]
步骤3:resp_b端调用nn_socket()接口创建消息分发库的套接字;
[0067]
步骤4:resp_b端调用nn_connect()接口连接到surv_a端绑定的地址;
[0068]
步骤5:resp_c端调用nn_socket()接口创建消息分发库的套接字;
[0069]
步骤6:resp_c端调用nn_connect()接口连接到surv_a端绑定的地址;
[0070]
步骤7:surv_a端调用nn_send()发送数据;
[0071]
步骤8:resp_c端调用nn_recv()接收数据,接收到surv_a发送的数据;
[0072]
步骤9:resp_c端调用nn_send()发送数据;
[0073]
步骤10:surv_a端调用nn_recv()接口接收数据,此时阻塞在此处;
[0074]
步骤11:resp_b端调用nn_recv()接收数据,收到surv_a端发来的数据;
[0075]
步骤12:resp_b端调用nn_send()发送数据;
[0076]
步骤13:surv_a端调用nn_recv()接口接收数据,此时阻塞解除;
[0077]
步骤14:resp_c端调用nn_close()接口关闭消息分发库的套接字;
[0078]
步骤15:resp_b端调用nn_close()接口关闭消息分发库的套接字;
[0079]
步骤16:surv_a端调用nn_close()接口关闭消息分发库的套接字。
[0080]
采用上述技术方案,本发明具有如下有益效果:
[0081]
本发明将大型通信软件系统协议间的通信场景抽象出直接通信的pair模型、订阅感兴趣事件的发布/订阅模型、双方应答的请求/回复模型、调查各节点情况的询问/确认模型,并且给开发人员提供统一的编程接口,提升系统扩展性和易维护性。
附图说明
[0082]
为了更清楚地说明本发明具体实施方式或现有技术中的技术方案,下面将对具体实施方式或现有技术描述中所需要使用的附图作简单的介绍,显而易见地,下面描述中的附图是本发明的一些实施方式,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
[0083]
图1为本发明实施例提供的系统框架图;
[0084]
图2为本发明实施例提供的发布/订阅模型;
[0085]
图3为本发明实施例提供的pair模型;
[0086]
图4为本发明实施例提供的请求/回复模型;
[0087]
图5为本发明实施例提供的请求/回复模型应用1;
[0088]
图6为本发明实施例提供的请求/回复模型应用2;
[0089]
图7为本发明实施例提供的询问/确认模型;
[0090]
图8为本发明实施例提供的系统调用和事件响应回调图;
[0091]
图9为本发明实施例提供的pair模型首先启动端传输层初始化时序图;
[0092]
图10为本发明实施例提供的pair模型首先启动端连接初始化时序图;
[0093]
图11为本发明实施例提供的pair模型首先启动端检测初始化时序图。
具体实施方式
[0094]
下面将结合附图对本发明的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
[0095]
以下结合附图对本发明的具体实施方式进行详细说明。应当理解的是,此处所描述的具体实施方式仅用于说明和解释本发明,并不用于限制本发明。
[0096]
结合图1至图11所示,本实施例提出一种支持多种通信模型的具有统一编程接口的消息分发库,包含直接通信的pair模型,订阅感兴趣事件的发布/订阅模型,双方应答的请求/回复模型,调查各节点情况的询问/确认模型;编程接口类似与socket套接字api,包含创建/关闭模型的nm_socket()/nm_close()接口,设置/获取模型参数的nm_setsocketopt()/nm_getsocketopt()接口,绑定模型地址nm_bind()接口,连接模型nm_connect()的接口,发送/接收模型数据nm_send()/nm_recv()的接口。
[0097]
本实施例中,模型中各节点通信的基础是linux提供的socket套接字编程接口,节点从创建模型,到绑定连接,再到双工通信,最后到关闭模型,是节点不同状态间的切换。显然,状态机是实现节点通信的恰当方案。
[0098]
本实施使用epoll技术实现节点收发数据的多路复用。
[0099]
大型通信系统软件关心网卡状态或路由状态等内核态事件,使用netlink技术可以基本满足内核态向用户态发送事件的要求。大型通信系统软件内核事件触发具有大量并发的特性,导致发布事件的内核任务忙,关注这些事件的用户态守护进程接收的事件可能失序,导致数据错误。本发明适配修改内核netlink分发事件流程,另创建一个内核任务和一个全局消息链表,将内核要分发的事件消息加入全局消息链表,再用创建的内核任务执行具体的分发事件工作。
[0100]
具体地,本实施例将消息分发机制系统划分六个大的功能模块,包括有用包(utils)、协议层(protocols)、传输层(transports)、连接层(core)、状态机(fsm)和线程池,如图1所示。utils实用工具包,包含基本数据结构(list,queue,hash)互斥及原子操作(mutex,atomic)等;protocols协议层实现包括pair、req/rep、pub/sub、survey协议模型,根据用户输入初始化模型实例,完成nn_sockbase接口中虚函数的实现;transports通信层实现包括进程间和tcp类型的通信类型,完成nn_epbase接口中虚函数的实现;core是transport和protocol等代码之间的连接层,负责各层之间的交流;状态机维护状态在连接,绑定,接受,对方连接断开状态之间正确运转;线程池提供线程给各协议任务运行。
[0101]
首先,详述协议层各模型的实现。假设协议a由进程a维护,协议b由进程b维护,协议c由进程c维护。
[0102]
现要求协议a和协议b可以相互通信且消息长度和消息量变化范围大。本发明由此抽象出pair模型,pair模型简单的一对一双工通信的模型,如图3所示。
[0103]
现要求协议a依赖协议b某状态值status_b,协议a在获取协议b状态值后才继续执行。本发明抽象请求/回复模型(应答模型),应答模型为用户的请求创建无状态服务,客户端发送请求,服务器接收请求,做一些处理,并返回响应,如图4所示;若协议a在获取协议b状态值status_b同时,还依赖协议c的状态值status_c,由status_b和status_c计算所得结果,决定协议a后续执行流程,可以由应答模型组成如图5所示拓扑图实现;若协议a依赖status_b和status_c的同时,还依赖协议d的状态值status_d(协议d启动的时候,协议b和协议c存在,协议a只依赖协议d;协议d未启动时,协议a才依赖协议协议b和协议c),可以由应答模型组成如图6所示拓扑图实现,给协议d设置较高的优先级。
[0104]
现要求协议b和协议c关心协议a的接口1状态status_if1,协议c关心协议a的接口2状态status_if2。本发明抽象发布/订阅模型,允许订阅者向发布者订阅感兴趣的事件,当发布者触发该事件后,会像所有订阅该事件的用户分发消息。如图2所示。
[0105]
现要求协议a管理设备资源resource_dev的创建和删除,协议b、协议c和协议d都会使用。若协议a删除资源resource_dev,需要协议b、协议c和协议d都停止使用资源resource_dev。协议a向外发出删除请求后阻塞,协议b、协议c和协议d收到后,如有使用资源resource_dev,则停止使用,向协议a返回成功;如没有使用,则直接向协议a返回成功。协议a收到所有发出去删除请求的应答后,解除阻塞,开始删除资源resource_dev。若有协议d在收到删除请求后,未向协议a返回应答之前,协议d闭关,此时协议a在收到协议b和协议c的应答后,会一直等待时间time_a后,待time_a超时后,协议a解除阻塞,根据返回结果失败与否决定后续删除流程。本发明抽象询问/确认模型(调查模型),允许在一个单一的请求里检查多个应用的状态,相当于是发布/订阅模型和请求/回复模型的合并,从一个节点发布
信息到多个节点,然后每个节点再返回信息,该模式可以一次查询后快速简单的得到多个系统的状态,并且调查对象必须在指定的时间内做出反应。如图7所示。
[0106]
其次,详述状态机的实现。状态机与基于事件驱动的机制运用于软件中,可以消除使用回调隐蔽成环的风险,清晰调用流程,方便日常维护。
[0107]
本发明将系统分层,上层到下层(从根节点到叶子节点方向)采用函数调用的方式,下层到上层(从叶子节点到根节点方向)采用事件发布的方式,如图8所示。系统各分层都有自己的状态机,上层进入某状态后,调用下层初始化函数,下层随即进入某状态后,调用更下层的初始化,直至叶子节点;叶子节点执行相关程序后,发布事件,激励临近上层状态机状态迁移,临近状态机迁移可能发布事件用以激励更上层的状态机,直至根节点或无状态需改变为止。上层状态机初始化后,依赖下层发布事件激励上层状态机的迁移,形成上层状态机嵌套下层状态机的情形。本发明的这种分层方式,严格规定了函数调用方向,清晰区分各层状态机的状态,简化了系统各层关系。
[0108]
现以pair模型首先创建pair实例的一端为例,分析其整个流程。用户首次调用nn_socket()会初始化linux系统的socket,初始化内存管理,启动线程池等系统初始化工作;之后调用nn_bind()开始运转pair模型,实际是激励状态机,如图9、图10、图11所示。
[0109]
创建nn_sock结构,nn_sock状态机由nn_sock_state_init状态进入nn_sock_state_active状态;
[0110]
由nn_sock创建nn_ep结构,nn_ep状态机进入nn_ep_state_idle状态;
[0111]
由nn_ep创建nn_bipc结构,nn_bipc状态机由nn_bipc_state_idle状态进入nn_bipc_state_active状态;
[0112]
由nn_bipc创建nn_usock结构,该结构管理linux系统分配的套接字socket,负责监听,
[0113]
nn_usock状态机由nn_usock_state_idle状态在创建linux系统套接字socket后进入nn_usock_state_staring状态,再调用linux系统函数listen()后进入nn_usock_state_listening;
[0114]
由nn_bipc创建nn_aipc结构,暂时接管nn_bipc,用来接管连接事件,nn_aipc状态机进入nn_aipc_state_idle状态;
[0115]
由nn_aipc创建nn_usock结构,nn_usock状态机进入nn_usock_state_idle状态;
[0116]
由nn_aipc创建nn_sipc结构,用于管理连接事件,nn_sipc状态机进入nn_sipc_state_idle状态;
[0117]
由nn_sipc创建nn_streamhdr结构,用于交换协议头,检测协议是否匹配,nn_sipc状态机进入nn_streamhdr_state_idle状态;
[0118]
由nn_sipc创建nn_pipebase结构,用于收发报文,nn_ep的sock交由nn_pipebase接管,nn_sipc状态机进入nn_pipebase_state_idle状态,入方向状态机进入nn_pipebase_instate_deactivated状态,出方向状态机进入nn_pipebase_outstate_deactivated状态。
[0119]
至此,本发明各层状态机的初始化基本完成,待系统套接字收发包事件到来,向工作线程发布事件激励上层状态机。
[0120]
再次,介绍有用包(utils)、传输层(transports)、连接层(core)和线程池。
[0121]
有用包包含本发明基本的基本数据结构(list,queue,hash)互斥及原子操作
(mutex,atomic),属于基本结构的封装。
[0122]
本发明考虑通信形式的不同,分类出两种传输类型,即进程间通信和tcp通信。进程间通信方式的传输类型,应用于本机设备内;tcp通信方式的传输类型,应用于不同设备间。传输层的分类,使得代码逻辑更清晰,使用更方便。
[0123]
协议层各模型统一抽象了一个函数列表,即nn_sockbase结构体,用户使用不同的模型会实例化不同的实例,用于发送或接收消息,设置或获取选项;传输层抽象一个函数列表,即nn_transport结构体,根据不同的传输类型实例化不同的实例。这些属于连接层。
[0124]
线程池根据协议层的模型数量创建线程数,用于处理下层对象向上层对象发布激励状态机的消息。同时通过epoll技术,监听系统中套接字或文件的输入输出事件。
[0125]
最后,简单介绍一下本发明类linux套接字的接口。包含创建/关闭模型的nn_socket()/nn_close()接口,设置/获取模型参数的nn_setsocketopt()/nn_getsocketopt()接口,绑定模型地址nn_bind()接口,连接模型nn_connect()的接口,发送/接收模型数据nn_send()/nn_recv()的接口。
[0126]
通过本发明,简化大型通信软件系统各模块间的通信方式,统一编程接口,使大型通信软件系统易于开发和维护,节省开发成本。
[0127]
最后应说明的是:以上各实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述各实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述各实施例所记载的技术方案进行修改,或者对其中部分或者全部技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明各实施例技术方案的范围。
当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1