客户端向服务器发送数据包(packet)时,首先将数据包放到改发送队列中,并不真实发送数据,而是发送数据就绪信号,等待loop事件循环调用的函数db__message_write根据网络连接情况来处理发送请求;该队列为单链表存储结构,每次有新数据包需要发送时,将新数据包插入到链表尾部;真正发送数据时从链表头部开始发送数据包。
阶段1、准备好需要发送的数据包,参见截图1的上半部分的单步断点处,非常关键,inflight_msgs就是在此处赋值的。
截图1的下半部分,每一个函数的跳转关系一目了然。
截图1
阶段2、在loop.c的事件循环里面,一直在调用函数db__message_write,通过它实现真正的发送,
/* Local bridges never time out in this fashion. */
if(!(context->keepalive)
|| context->bridge
|| now - context->last_msg_in <= (time_t)(context->keepalive)*3/2){
if(db__message_write(db, context) == MOSQ_ERR_SUCCESS){ //firecat,real_send_publish
该函数体在database.c定义,它反复在判断inflight_msgs是否为空。不为空表示有待发送的数据包。
截图2
个人建议:
在单步调试,查看业务主题消息流程时,建议把系统主题的消息屏蔽掉。方法如下:
1、/src/mosquitto.c,第294行,代码注释掉
#ifdef WITH_SYS_TREE
//sys_tree__init(&int_db);//firecat,SYS,"$SYS/broker/#"
#endif
2、/src/loop.c,第204行,代码注释掉
if(db->config->sys_interval > 0){undefined
//sys_tree__update(db, db->config->sys_interval, start_time);//firecat,SYS,"$SYS/broker/#"
}
或者干脆一点,在CMakeLists直接把宏WITH_SYS_TREE设置成未定义。