mosquitto源码分析报告

上传人:无*** 文档编号:105882498 上传时间:2022-06-12 格式:DOC 页数:21 大小:436.50KB
收藏 版权申诉 举报 下载
mosquitto源码分析报告_第1页
第1页 / 共21页
mosquitto源码分析报告_第2页
第2页 / 共21页
mosquitto源码分析报告_第3页
第3页 / 共21页
资源描述:

《mosquitto源码分析报告》由会员分享,可在线阅读,更多相关《mosquitto源码分析报告(21页珍藏版)》请在装配图网上搜索。

1、 . mosquitto源码分析本文由逍遥子撰写,转发请标注原址:一、 Mosquitto简介mosquitto是一款实现了消息推送协议MQTT v3.1 的开源消息代理软件,提供轻量级的,支持可发布/可订阅的的消息推送模式,使设备对设备之间的短消息通信变得简单,例如现在应用广泛的低功耗传感器,手机、嵌入式计算机、微型控制器等移动设备。Mosquitto采用出版/订阅的模式实现MQTT协议,这种设计模式将通信终端之间的关系统一到效劳程序中进展管理,可极大减轻客户端的开发和维护工作。1.1、 mqtt协议简介MQTTMessageQueuing Telemetry Transport,消息队列遥

2、测传输是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成局部。在某些应用场合中,可通过该协议维持与客户端的长连接。关于mqtt协议更详细的介绍,请参考其官方:mqtt.org/其个版根源码下载位置:mosquitto.org/files/source/1.2、 出版/订阅模式简介出版/订阅模式定义了如何向一个节点发布和订阅消息,这些节点被称作主题(topic)。主题可以被认为是消息的传输中介,发布者(publisher)发布消息到主题,订阅者(subscriber) 从主题订阅消息。这种模式使得消息订阅者和消息发布者保持互相独立,不需要接触即可保证消息的传送。Tcp协议中,tcp连接只

3、提供一对一的可靠传输,例如:主机A与B进展通信,那么发起tcp连接的一端只需要知道对方的ip地址和端口号即可,如下列图1-1所示:图1-1 一对一通信每一个tcp连接都是由下面的五个元素确定:在实际程序的开发过程中 一条连接建立之后,它可能需要在一段时间一直被通信双方所保持,以备下次数据传输使用。另外,通信的终端数目可能是多个,这就需要每个终端都要维持它所有的通信关系,如下列图1-2所示图1-2 多对多通信此时,每个参与通信的客户端所需维持的连接数量将非常庞大,这非常不利于程序的开发和实现。出版/订阅模式即是一种解决这种问题的方法,它通过增加一个中间层的方式,让中间层来维护这种多对多的关系,这

4、个中间层通常称之为效劳器,如下列图1-3所示:图1-3 增加中间层的多对多通信通过增加中间层效劳器,每个客户端都只需要维护自己同效劳器之间的连接即可,而客户端之间的关系那么交由中间效劳器来维护,这种设计模式将复杂的通信关系维护工作从客户端剥离出来,非常方便客户端的开发和维护。Mosquito程序即是通过这种方式进展工作,在mosquitto程序部,将客户端之间的关系通过一棵订阅树来维持。1.3、 MosquitoMosquito源码目录结构介绍。|- mosquitto-1.2|- client|- examples |-mysql_log |-temperature_conversion|-

5、 installer|- lib |- cpp |- jsws |-python|- logo|- man |- po |-libmosquitto |-mosquitto |-mosquitto.conf |-mosquitto_pub |-mosquitto_sub |-mosquitto-tls |-mqtt|- misc |-currentcost |-gnome-panel|- security|- service |- monit |-svscan |-upstart|- src |-db_dump|- test |-broker |- c |- lib |- c |-cpp |-

6、python |-python3 |- ssl |-demoCA |-rootCA |-signingCA所需关注的目录有/ mosquitto-1.2/src、/ mosquitto-1.2/lib、/ mosquitto-1.2/client三个目录,其中src和lib目录下主要放置mosquitto的实现代码以与局部底层与网络相关的操作,client目录主要为两个客户端程序的实现源码。Mosquito的源码与其相关文档可从其官方获取,其官方为:mosquitto.org/mosquitto客户端和效劳器运行命令二、 Mosquito的数据结构1struct mosquito结构体stru

7、ct mosquito主要用于保存一个客户端连接的所有信息,例如用户名、密码、用户ID、向该客户端发送的消息等,其定义为:struct mosquitto int sock; char*address; char *id; char*username; char*password; uint16_tkeepalive; time_tlast_msg_in; time_tlast_msg_out;struct mosquitto_client_msg *msgs;上面列举了该结构体局部重要成员,其中sock表示mosquitto效劳器程序与该客户端连接通信所用的socket描述符;address

8、表示该客户端的IP地址;id是该客户端登陆mosquitto程序时所提供的ID值,该值与其他的客户端不能重复;成员username和password用于记录客户端登陆时所提供的用户名和密码;keepalive是该客户端需在此时间向mosquitto效劳器程序发送一条ping/pong消息。参数last_msg_in和last_msg_out用于记录上次收发消息的时间;参数struct mosquitto_client_msg*msgs用于暂时存储发往该context的消息。2struct mosquitto_db结构体struct mosquitto_db是mosquitto对所有部数据的统一

9、管理结构,可以认为是其部的一个存数据库。它保存了所有的客户端,所有客户端的订阅关系等等,其定义形式为:struct mosquitto_db dbid_tlast_db_id; struct_mosquitto_subhier subs; struct mosquitto*contexts; struct_clientid_index_hash *clientid_index_hash; intcontext_count; structmosquitto_msg_store *msg_store; intmsg_store_count; structmqtt3_config *config;

10、intsubscription_count;上述结构体声明中,结构体成员struct _mosquitto_subhier subs保存了订阅树的总树根,mosquitto中对所有的topic都在该订阅树中维护,客户端的订阅关系也在该订阅树中维护;结构体成员struct mosquitto *contexts可理解为一个用于存放所有客户端变量类型为struct mosquitto地址的数组,mosquitto程序中,所有的客户端都在此数组中保存;成员int context_count用于保存数组contexts的大小,该值也是当前mosquitto程序中维持的所有客户端的数目;成员结构体str

11、uct _clientid_index_hash*clientid_index_hash用于保存一个hash表,该hash表可通过客户端的ID快速找到该客户端在数组contexts中的索引;结构体成员struct mqtt3_config*config用于保存mosquitto的所有配置信息;3struct_mosquitto_subhier数据结构struct _mosquitto_subhier是用于保存订阅树的节点包括叶子节点和中间节点,mosquitto中对订阅树采用孩子-兄弟链表法的方式进展存储,该存储方式主要借助与数据结构struct _mosquitto_subhier来完成,该

12、数据结构的定义为:struct _mosquitto_subhier struct_mosquitto_subhier *children; struct_mosquitto_subhier *next; struct_mosquitto_subleaf *subs; char*topic; structmosquitto_msg_store *retained;成员说明:children :该成员指针指向同结构的第一个孩子节点;next:该成员指针指向该节点的下一个兄弟节点;subs:该成员指向订阅列表;topic:该节点对应的topic片段;4struct _mosquitto_suble

13、af在mosquitto程序中,对某一topic的所有订阅者被组织成一个订阅列表,该订阅列表是一个双向链表,链表的每个节点都保存有一个订阅者,该链表的节点即是:struct _mosquitto_subleaf,定义形式为:struct _mosquitto_subleaf struct_mosquitto_subleaf *prev; struct_mosquitto_subleaf *next; structmosquitto *context; int qos;其中成员struct mosquitto *context表示一个订阅客户端,prev和next表示其前一个节点和后一个节点。5

14、structmqtt3_config结构体struct mqtt3_config用于保存mosquitto的所有配置信息,mosquitto程序在启动时将初始化该结构体并从配置文件中读取配置信息保存于该结构体变量。三、 Mosquito的核心功能分析3.1、订阅树Mosquitto通过订阅树的方式来管理所有的topic以与客户端的订阅关系,它首先将所有的topic按照/分割并组织成一棵树结构,从根节点到树中的每个节点即组成该节点所对应的一个topic,每个topic都保存一个订阅列表,该订阅列表中保存了所有订阅当前topic的客户端信息。例如有如下订阅关系:客户端a1,a2,a3订阅了topi

15、c:A1/B1/C1客户端b1,b2订阅了topic:A2/B2/C2客户端c1,c2订阅了topic:A1/B1/C3客户端d1订阅了topic:A2/B3那么在mosquitto程序中需要先将topic按照/进展分割,然后将分割后的topic片段组织成订阅树,上述订阅树的示意图为图3-1:图3-1 订阅树示意图Mosquitto程序在实现中根据topic消息的性质将订阅树分为两颗子树:业务子树和系统子树;mosquitto程序中将topic分为两种类型来处理:系统topic和业务topic,前者主要用于发布和维护mosquitto部的系统消息,后者的topic是用户订阅的业务topic,做

16、这种区分的原因是因为这两种的类型的topic性质和实现方式上有许多差异,这种差异主要表达在以下4点:1生存周期不同,系统topic无论是否有用户订阅都会存在与订阅树中,而业务topic必须有客户端订阅才能存在除非其消息字段retain设置为1;2创立方式不同,系统topic在消息发布时进展创立,业务topic即可以在订阅时创立也可以在消息发布时创立此时需要该消息retain字段设置为1;3消息保存方式不同,但凡发布到系统topic的消息都会被保存下来,业务消息将直接挂到订阅列表的各context的消息队列中,如果没有连接订阅或未设置其retain字段,消息将不会被保存下来;消息的retain字

17、段是否被设置在函数mqtt3_handle_publish进展检查,在该函数中有如下代码:retain = (header & 0x01);该代码可获取消息头部的第一个bit位,在mqtt3.1协议中,该为用于表示消息的类型是否为retain。订阅树在程序中的采用孩子兄弟链表法来表示。其主要涉与的数据结构是:struct _mosquitto_subhierstruct _mosquitto_subleaf、订阅树的搭建1、创立订阅树mosquitto程序启动时将创立订阅树,该过程将创立三个节点:订阅树总根节点、业务子树根节点和系统子树根节点,这两个子树根节点作为订阅树总根节点的两个子节点,其

18、中订阅树总根节点和业务子树的根节点中topic成员的值为空字符串,而系统子树根节点中保存的值为“$SYS,如图3-2所示。图3-2 订阅树的创立订阅树的创立主要在文件database.c中mqtt3_db_open函数里实现。订阅树中节点的数据结构为struct _mosquitto_subhier,订阅树采用“孩子兄弟链表法保存。2、搭建订阅树在订阅树中,系统子树与业务子树的搭建过程不一样,系统子树是在系统消息发布时创立,而业务子树创立过程即可以在消息发布时创立也可以在客户端订阅时才创立。1)系统子树搭建过程Mosquitto中,系统子树在发布系统消息时,自动检测topic片段是否存在,如果

19、不存在那么在系统topic上创立节点以搭建订阅树。例如,mosquitto程序启动时,将首先向系统topic:$SYS/broker/version发送一条版本消息“mosquittoversion 1.2”,此时订阅树的系统子树只有一个根节点,如图3.2所示,其搭建过程如下:(1)将topic按照/分成topic片段,系统Topic:$SYS/broker/version将被分割为$SYS、broker、version三局部。(2)根据第一个topic片段“$SYS遍历订阅树的子节点找到系统子树的根节点。(3)根据topic下一个片段“broker查找系统子树;此时系统子树中不存在topic

20、片段“broker的节点,那么为订阅树产生一个节点,其数据结构为:struct_mosquitto_subhier。此时订阅树由图3-2变为图3-3所示:图3-3添加broker节点之后的订阅树上述过程在函数mqtt3_db_messages_queue中调用函数_sub_add来完成。(4)依此处理topic剩下的片段,在系统子树中添加topic片段“version,该过程通过递归调用函数_sub_add来完成。添加完“version片段之后的订阅树如图3-4所示。图3-4添加version之后的订阅树系统子树搭建过程中,所用到的函数调用关系如下列图3-5所示图3-5 系统子树搭建的函数调用

21、关系2) 业务子树搭建过程业务子树的搭建分为两种类型:一种在订阅时创立;一种是在消息发布时创立,这种方式与系统topic的创立过程一样,因此下面的容将主要描述前一种方式。在mosquitto程序运行期间,收到一条客户端的订阅请求后将调用函数mqtt3_sub_add将该客户端挂到对应的业务子树节点的订阅列表中,此时,如果所订阅树中不存在客户端所订阅的topic,那么会自动为之添加相应的节点,此过程即为订阅树的业务子树搭建过程。例如,在mosquitto程序启动时此时订阅树如图3-2所示客户端订阅了topic:year/month/events,业务子树的搭建过程为:(1)将topic按照/分成

22、topic片段,topic:year/month/event将被分割成:year、month、events三个topic片段;此过程在函数mqtt3_sub_add中完成。(2)遍历订阅树的第一级子节点,以查找业务子树的根节点,找到业务子树的根节点之后进展后续的处理。此过程在函数mqtt3_sub_add中完成。(3)依此处理三级topic片段:year、month、events,此过程与系统topic的添加过程相似,如果订阅树中不某个存在topic片段,那么为订阅树添加此节点,添加完成之后的订阅树如图3-6:本条功能在函数_sub_add中完成。图3-6 添加业务topic之后的订阅树业务子

23、树搭建过程中,所用到的函数调用关系如下列图3-7所示图3-7 业务子树搭建的函数调用关系、使用订阅树发布消息在Mosquito程序中,消息发送过程主要通过遍历订阅树来完成,具体为:递归遍历订阅树找到指定的订阅列表,并将消息挂到订阅列表中的每个contextg的消息队列中,如果消息的retain字段被设置为1,那么mosquitto还需要保存此消息,以备新订阅的客户端可以立即收到上次发送的消息;另外,发往系统topic的消息也会被mosquitto保存起来。上述消息发送过程主要通过函数mqtt3_db_messages_queue来完成。另外,根据mqtt协议,mosquitto还对#和+两个通

24、配符提供支持,通配符#可放在topic的第一级之外的其他topic片段中,用以表示匹配所有后续topic片段,例如:a/# 可以匹配a/b、a/b/c、a等,但是#需要独立为一个分级才能起作用,即a/b#c/d这种情形不被支持。通配符用“+用以匹配一级topic,例如a/+/c可以匹配a/b/c、a/d/c但是不能匹配a/d/f。另外消息的qos等级不同,mosquitto对消息的发送过程也不一样。例如,在如图3-8所示的订阅树中, 以qos为0时发布消息为例,消息发布时通过mqtt3_db_messages_queue完成。图3-8 订阅树的遍历向topic:year/month/event

25、s1发送消息,其发送过程为:1) 将topic按照/分成topic片段:year、month、event1s三个topic片段;该topic分片过程在函数mqtt3_db_messages_queue中完成。2) 遍历订阅树根的子节点,并根据第一级topic分片的类型是否为“$SYS选择业务子树还是系统子树进展递归遍历。同时还需判断消息中retain标识位是否设置为1,如果是,那么需将该topic的所有后续分片参加到订阅树中,经过该添加之后,订阅树中就存在了该topic,这一添加topic片段的过程在函数_sub_add中完成。3) 递归遍历子树,每次选取一个topic分片,将之与当前的节点的

26、所有子节点进展比拟,以找到匹配的节点,然后继续递归匹配下去,递归处理过程主要由函数_sub_search完成;4) 当匹配完所有的topic分片或者遇到topic分片为#时,进展如下处理:5) 当消息的retain字段被设置为1之后,需要将该消息持久化,即保存下来,以备有新订阅者订阅该topic的消息时可以收到上一条消息。6) 遍历当前订阅树节点的订阅列表,将消息挂载所有订阅者的消息队列中,此过程通过函数mqtt3_db_message_insert完成。mosquitto消息发送过程中所调用函数的关系如下列图3-9所示:图3-9 消息发布函数调用关系图、从订阅树中删除订阅客户端在Mosqui

27、tto程序中,客户端可以向mosquitto效劳器发送取消对某个topic的订阅请求,效劳器收到请求之后,将从订阅树中删除该客户端,该过程需要遍历订阅树以找该topic在订阅树中的位置,进而获得到订阅该topic的订阅列表,从而将其从订阅树中删掉。该过程与发送消息类似,首先将topic进展分片,然后根据topic片段遍历订阅树找到该topic的订阅列表;然后遍历订阅列表,将该客户端从订阅列表中删除。取消订阅的函数调用关系如图3-10所示。图3-10 取消订阅函数调用关系、订阅树机制的优缺点分析Mosquito程序采用订阅树形式维护客户端之间的订阅与发布消息,这种方式优点是逻辑清晰,便于开发和维

28、护。缺点是其遍历过程效率较低。同时,程序中存在很多对订阅树的遍历过程:订阅、发布消息、取消订阅等,在客户端数量增加时,该功能对效率的影响将更为明显。因此,在mosquitto的实际应用中很难支持5万以上的客户端,尤其在客户端网络状态不好时,其断开重练操作将非常频繁,这样也造成大量对订阅树的遍历操作,从而严重影响mosquitto的效率。3.2、mosquitto的消息收发机制Mosquito最主要的功能就是对消息的正确接收、维护和转发,因此其消息的接、收功能非常重要。Mosquitto的消息收发主要通过poll机制来完成。、poll机制简介Poll机制是一种I/O多路转接I/O multipl

29、exing技术,这种技术先构造一个有关描述符的表,然后调用一个函数,知道这些描述符中的一个已准备就绪好进展I/O时,该函数才返回,该函数返回之后它告诉进程那些描述符已经准备好进展I/O)。其工作过程为:1首先构造一个pollfd结构数组,每个数组元素指定一个描述符编号以与对其所关心的状态。2为每一个需要监听状态的设备描述符创立一个pollfd结构体,并将之放入pollfd结构数组中。3调用函数poll监控pollfd结构数组中每个结构体的状态。Poll函数的原型如下:int poll(struct pollfdfdarray, nfds_t nfds, int timeout)其中参数fdar

30、ray就是pollfd结构体数组,nfds是数组的元素数,timeout是等待超时限定,如果超过此时间还没有描述符准备好I/O,就返回;pollfd结构体的定义为:struct pollfdint fd;short event;short revent;其中,int fd是文件描述符,在mosquitto的中主要指socket描述符在linux一切I/O皆文件的工作模式下,socket描述符与普通文件描述被同等对待;events成员用于告诉核,我们对描述符fd关心什么;revents用以说明该描述符fd发生了什么事情。另外,使用poll是需要注意,每次调用poll函数之前都要重新设置一下各描述

31、符的状态。、mosquitto的消息机制Mosquito在工作过程中用poll机制检测监听所有socket以判断其是否有数据发送或接收,mosquitto所监听的socket按照其功能分为监听socket和业务socket,监听socket主要负责监听各客户端的连接;业务socket主要负责mosquitto效劳器与各客户端之间的数据收发;一旦mosquitto效劳器从监听socket中接收到一个客户端连接进来,将立即为该客户端创立一个业务socket,负责后续mosquitto效劳器与该客户端的所有数据收发。Mosquitto中对poll操作主要在/ mosquitto-1.2/src lo

32、op.c文件的mosquitto_main_loop函数中,在该函数中将按照以下步骤循环处理所有的socket:1创立pollfd结构体数组pollfds2将要监听的socket放入pollfds3使用poll函数查询pollfds数组中各描述符的状态;4Poll函数返回之后,遍历pollfds数组对其中就绪的socket描述符进展处理。mosquitto_main_loop函数不仅涉与对poll函数的相关处理,它也是整个消息处理架构的实现之处,该函数对消息处理的流程如下列图3-11图3-11 mosquitto函数的消息业务处理流程在上述消息处理过程中,poll函数返回之后,pollfds数

33、组中socket描述的pollfd结构的revents成员就会置为相应的就绪状态,因此只要循环扫描该数组,即可根据对应socket完成相应的读写操作。在mosquitto程序中,poll函数所监听的socket有两种类型:监听socket和业务socket,其对应的结果处理函数就分两个过程来完成。监听socket处理过程主要在mosquitto_main_loop函数中直接完成,它主要完成的工作是处理每个监听socket,如果有客户端连接进入时,为之创立一个业务socket和一个对应的context结构体,context结构体描述了该连接的所有信息,因此在mosquitto程序中,一个cont

34、ext就表示一个客户端连接。业务socket的处理主要通过loop_handle_reads_writes函数完成,在该函数中将循环检查所有的context,如果该context对应的socket有数据写入那么调用函数_mosquitto_packet_write进展写操作;如果对应的socket有数据要读取,那么调用函数_mosquitto_packet_read完成socket的读取和处理,其中读取消息的处理在函数mqtt3_packet_handle中完成,在该函数中将根据不同的消息类型,调用不同的处理函数,业务socket的消息读取与其处理的函数调用关系如图3-12所示。图3-12 消

35、息读取和处理函数调用关系、mosquitto的消息收发本文中,消息的收发是相对mosquitto效劳器而言,Mosquito的消息的收发主要包括以下两个过程:1、消息接收过程是mosquitto效劳器接收到客户端向某个主体发布一条消息。2、消息发送过程是指Mosquito效劳器将消息发送给订阅客户端。在mosquitto的程序实现中,上述两个过程是分开实现和操作的:消息接收过程,Mosquitto效劳器端在收到客户端向某个主体发送的消息之后,会遍历订阅树,找到该主体的订阅列表,然后将消息挂到订阅列表中每个订阅者的消息队列中。需注意的是,此时消息并实际发送给订阅客户端,只是被挂在了mosquit

36、to效劳程序中该客户端对应的context结构中所定义的消息队列中;上述工作过程涉与到的主要函数与其调用过程可参照图3-9所示。Mosquitto的消息的组装发送过程集中在函数mqtt3_db_message_write中完成,其函数调用关系如下列图3-13所示。图3-13 消息组装和发送函数调用关系3.3、mosquitto的ping/pong功能1、为什么mosquitto要引人ping/pong的操作根据tcp/ip协议的描述,tcp连接建立之后,如果双方没有通信,连接可以一直保存下去,假设中间路由器崩溃或者中间的某条线路断开,只要两端的主机没有被重启,连接就一直被保持着。尽管tcp协议

37、规中未做次要求,但是在很多tcp协议的实际实现中,却提供了保活定时器的功能,保活定时器一般配置的时间是2小时。在实际的效劳器程序开发过程中,2个小时的连接断开的时间太长。因此,很多效劳器程序都在上层自己提供保活功能,也就是效劳器程序开发过程中经常提到的:心跳连接或ping/pong消息等功能。2、mosquitto的ping/pong功能描述在mosquitto中,提供了ping/pong功能来判断连接异常断开的情况,并通过keepalive的参数来控制检查时间,一般客户端需要在keepalive时间向效劳器发送一条消息,说明自己还存在,效劳器会周期检查与客户端建立起的每一个连接,如果某个连接

38、在keepalive*1.5的时间没有收到过消息,那么认为这个连接就失效了,于是效劳器将主动断开这个超时的连接。Mosquitto中,每个客户端所对应的context中有两个变量last_msg_out和last_msg_in,分别用于记录该context上次发送和接收消息的时间,然后在mosquitto_main_loop位于文件loop.c中每次循环都对每个context的所记录的消息收发时间进展检查,如果超过设定的keepalive时间的1.5倍那么断开此客户端的连接,因此,如果mosquitto客户端在keepalive时间与mosquitto效劳器之间存在任何通信无论是普通消息还是p

39、ing/pong消息,都是如此,mosquitto就认为该客户端是连接状态良好的。3、ping/pong功能对mosquitto性能产生的潜在影响Mosquitto以keepalive*1.5时间作为判断客户端连接是否异常断开的时间界限,这里keepalive的值对mosquitto的性能会产生较大影响,此值过大,可能无法与时判断处异常的发生;此值过小,不仅浪费网络带宽,还可能造成误判,例如客户端与效劳器之间tcp连接上的某个效劳器异常重启,可能会被效劳器误判为tcp连接断开了。此值需根据实际情况分析后确定。四、 Mosquito的辅助功能介绍Mosquitto代码的辅助功能主要包括:log输

40、出功能、配置参数管理功能和存封装的功能,这三个功能虽不是mosquitto的核心模块,但是却在其源码实现中经常遇到,它们的实现给mosquitto的代码开发带来了很大的方便。4.1、log输出功能Mosquitto日志输出功能的实现代码主要在文件/ mosquitto-1.2/src/logging.c中。Mosquitto的log模块具备以下功能:日志分等级输出、日志的多平台输出、日志对各种参数的格式化输出;mosquitto的日志模块初始化由函数mqtt3_log_init完成,该函数主要完成对日志输出位置以与日志输出等级两个参数的设置。函数mqtt3_log_close完成日志模块的关闭

41、功能。日志模块的输出由函数_mosquitto_log_printf完成,该函数的声明形式为:int _mosquitto_log_printf(struct mosquitto *mosq, int priority,const char *fmt, .) 其中第一个参数struct mosquitto *mosq表示某客户端连接所对应的上下文信息,该参数可以为空;第二个参数int priority表示日志的优先级,在mosquitto的配置文件mosquitto.conf中将会配置日志的输出等级,如果传给函数的日志等级低于配置文件中的等级配置,该条日志将不被输出。另外,该函为一可变参数的函

42、数,在使用过程中可以根据需要将参数进展格式化输出。例如下一条日志输出语句:_mosquitto_log_printf(NULL,MOSQ_LOG_NOTICE, Client %s disconnected., client_id);在该条日志输出语句中,将保存在client_id中的客户端ID格式化到字符串Client %s disconnected.中作为本条日志输出的容,本条日志输出的等级为MOSQ_LOG_NOTICE。4.2、配置参数管理Mosquitto参数配置功能的实现代码主要在文件mosquitto-1.2/src/conf.c中,配置文件保存路径为:mosquitto-1.2

43、/ mosquitto.conf,在mosquitto程序中主要由结构体structmqtt3_config保存从配置文件中读取的各参数值。Mosquitto的配置参数管理功能主要包括对配置文件的读取和解析、对用户输入参数的解析以与对配置文件结构体的管理三局部Mosquitto对外提供的操作接口均以“mqtt3_config_开头,共有以下四个:(1)mqtt3_config_init该函数的声明为:void mqtt3_config_init(struct mqtt3_config *config)它主要完成对参数config的各结构体成员的初始化工作。(2)mqtt3_config_cle

44、anup该函数的声明为:void mqtt3_config_cleanup(struct mqtt3_config *config)它主要完成对参数config的各成员的去除、释放等操作。(3)mqtt3_config_read该函数的声明为:int mqtt3_config_read(struct mqtt3_config *config, bool reload)它主要完成从配置文件中读取各配置参数到结构体config中,具体的配置文件读取工作由函数_config_read_file完成。(4)mqtt3_config_parse_args该函数的声明为:int mqtt3_config_

45、parse_args(struct mqtt3_config *config, intargc, char *argv)它主要完成对用户输出参数的解析工作。Mosquitto的配置文件部共提供对整形、布尔类型,字符串三种类型的解析函数,这三个解析函数只共部调用,分别是:_conf_parse_bool、_conf_parse_int、_conf_parse_string。4.3、存操作的封装Mosquitto对存操作的封装代码主要在文件mosquitto-1.2/src/memory_mosq.c中实现,共实现了对常用的存申请与释放相关的系统调用函数,共有:_mosquitto_calloc函数是对系统函数calloc的封装,_mosquitto_malloc函数对系统函数malloc的封装,_mosquitto_realloc函数对系统函数realloc的封装,_mosquitto_free函数对系统函数free的封装,_mosquitto_strdup函数对系统函数strdup的封装。在上述封装函数中如果文件中定义了宏REAL_WITH_MEMORY_TRACKING,那么这些封装函数只是对系统函数进展封装,不做任何额外操作。如果定义了REAL_WITH_MEMORY_TRACKING宏,那么会在存申请和释放时分别记录所申请或释放存的大小。21 / 21

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!