分享

mqtt3_sub_tree_print函数的运用与分析

 风雪夜归人_95 2014-12-02
引言:
在mosquitto源码的src/subs.c 文件中存在一个mqtt3_sub_tree_print,它的作用是打印整个订阅树。这实际上也是遍历整个订阅树查找的过程,对于理解订阅树、当前sever端存储的内容都有十分重要的帮助。

如何调用mqtt3_sub_tree_print
      笔者发现调用它需要开启另一个bool型变量flag_tree_print,该值默认情况下为false,故不打印树结构。这个变量是在src/mosquitto.c中定义,而在src/mosquitto.c文件中的handle_sigusr2()函数使这个变量为true。即当server端收到SIGUSR2信号时就会打印该信息。那什么是SIGUSR2?度娘告诉我们,它是一个自定义信号,这个信号由这条命令“kill -USR2 14932(PID号)”产生。当然,具体到这里,也就是当你在一个窗口内键入“mosquitto”时,开启新的窗口,输入刚才的命令,则在第一个窗口中可以显示打印出来的订阅树信息。

mqtt3_sub_tree_print原型
 void mqtt3_sub_tree_print(struct _mosquitto_subhier *root, int level)
{
        int i;
        struct _mosquitto_subhier *branch;
        struct _mosquitto_subleaf *leaf;

        for(i=0; i<level*2; i++){
                printf(" ");
        }
        printf("%s", root->topic);
        leaf = root->subs;
        while(leaf){
                if(leaf->context){
                        printf(" (%s, %d)", leaf->context->id, leaf->qos);
                }else{
                        printf(" (%s, qos:%d)", "", leaf->qos);
                }
                leaf = leaf->next;
        }
        if(root->retained){
                printf(" (r)");
        }
        branch = root->children;
        while(branch){
                mqtt3_sub_tree_print(branch, level+1);
                branch = branch->next;
        }
}

没有客户与server端连接
其打印结果为:
 这是在没有任何客户端连接的情况下的订阅树,那么也就意味着这里的所有元素都是在系统子树中存在的。从最开始的“$SYS”也可以看出这其中的端倪。但是细心的你会发现在第一个"$SYS”的上面有两行空行,为什么会在最开始有两行空行呢?为了看得更清楚在源码基础上加了适当的打印信息,观察结果。
 可以看到,实际上,前面的两行执行了两次搜索,很明显这里是在业务子树中搜索了两层后,由于这两层的主题为“”,故其打印为空。那为什么是两层呢?笔者猜测这应该和mosquitto本身实现有关。系统子树中分了两层“$SYS”,推测业务子树也是分了两层。新添加的用户订阅的新主意也是从这两层之下开始添加的。

有一个订阅主题的客户连接
其结果为:
 可以看到,这里和前面没有客户端连接时发生了两个变化:
1)第一行多了一个“mqtt”主题的相关信息打印(用户ID号和 qos值)
2)最后又添加了一个叫做“load”的子树(这个子树有点庞大了)

对于第一行的变化自然很好理解的,因为这是客户端自己订阅的,订阅树发现没有则自动添加,很正常。可是第二个变化,这个庞大的load子树又是从哪里出来的呢?它的作用又是什么呢?这些都不得而知。
经过源码分析发现,load子树的添加发生在mqtt3_db_sys_update函数(src/sys_tree.c)中,而这个函数又是在mosquitto_main_loop函数(src/loop.c,对消息的正确接收、维护和转发)中被循环调用。而且load子树只会在有客户端连接(无论是publish还是subscribe,不过在使用publish的时候,发现其添加load子树会有一个推迟,即publish后立即打印订阅树,load子树未被添加,但过一段时间如2秒再打印,则子树添加,而subscribe还没出现这种情况)。具体可以分析
mqtt3_db_sys_update函数,实际上,load子树的添加与否和socket连接时的一些时间参数有关。比起这个,笔者更关心的是load子树的作用是什么。
从其topic的命名来看应该也可以看出一些端倪,但是这里出现的1min、5min、15min表示不能理解。



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多