第一篇,先简单分析一下整个emqtt 的大致结构,包括两个部分:

1、message packet 类型

2、message 流向

message packet 类型

P1:mqtt_packet 的基本结构,其中header 中的type 与variable 的mqtt_packet_* 一一对应。

emqtt 的packet 定义如下:

 -record(mqtt_packet,
{header :: #mqtt_packet_header{},
variable :: #mqtt_packet_connect{} | #mqtt_packet_connack{}
| #mqtt_packet_publish{} | #mqtt_packet_puback{}
| #mqtt_packet_subscribe{} | #mqtt_packet_suback{}
| #mqtt_packet_unsubscribe{} | #mqtt_packet_unsuback{}
| mqtt_packet_id() | undefined,
payload :: binary() | undefined }).

包括包头、包的类型、实际的数据消息。

在emqtt 中,message packet 的类型主要分为一下几类(这些类型,基本上定义在emqttd_protocol.hrl 文件中):

1、connect/connack

P2:connect packet的基本结构

用于客户端向server端建立链接以及server 端向client 确定链接。

 -record(mqtt_packet_connect,
{client_id = <<>> :: mqtt_client_id(),
proto_ver = ?MQTT_PROTO_V311 :: mqtt_vsn(),
proto_name = <<"MQTT">> :: binary(),
will_retain = false :: boolean(),
will_qos = ?QOS_0 :: mqtt_qos(),
will_flag = false :: boolean(),
clean_sess = false :: boolean(),
keep_alive = 60 :: non_neg_integer(),
will_topic = undefined :: undefined | binary(),
will_msg = undefined :: undefined | binary(),
username = undefined :: undefined | binary(),
password = undefined :: undefined | binary()}). -record(mqtt_packet_connack,
{ack_flags = ?RESERVED :: 0 | 1,
return_code :: mqtt_connack() }).

其中,主要的几个字段,client_id、proto_ver、proto_name以及keep_alive。

client_id在username undefined的情况下,充当username的角色,是客户端的唯一标识,在接下来的session manage以及 subscription 管理中,具有非常重要的作用。

2、subscribe/suback

P3:subscribe packet的基本结构

用于处理客户端 subscribe 某个topic,已经server端向客户端的确认。

 -record(mqtt_packet_subscribe,
{packet_id :: mqtt_packet_id(),
topic_table :: list({binary(), mqtt_qos()}) }).
-record(mqtt_packet_suback,
{packet_id :: mqtt_packet_id(),
qos_table :: list(mqtt_qos() | 128) }).

topic_table 字段表示的是所要subscribe的topic 以及对应的QoS。

3、unsubscribe/unsuback

subscribe的反向操作

4、publish/puback

P4: publish packet的基本结构

 -record(mqtt_packet_publish,
{topic_name :: binary(),
packet_id :: mqtt_packet_id() }). -record(mqtt_packet_puback,
{packet_id :: mqtt_packet_id() }).

topic_name指定了将要publish到的topic的名字。

在emqtt中,用Erlanger中record数据类型,定义了以上一种message packet的类型,而且,这些类型的packet的作用都显而易见。

message 流向

首先,mqtt是基于TCP协议的,因此,emqtt本身也是架构在TCP server上的service。其底层,基于esockd(主要借鉴RabbitMQ networking的实现)。socket controlling 进程的执行逻辑是emqttd_client module。emqttd_client module主要与esockd application 中的esockd_connection module 相关联,并存在必要的callback 关系。

由于socket controlling 进程的入口以及主要执行逻辑由emqttd_client module实现。

因此:

  • message进入到server后,首先由emqttd_client module进行处理

进入到emqtt server的message,主要是二进制socket数据,想要转换成Erlang的内部数据结构,就必要进行必要的数据解析。

1、socket 数据包接收

 handle_info({inet_async, _Sock, _Ref, {ok, Data}}, State) ->
Size = size(Data),
?LOG(debug, "RECV ~p", [Data], State),
emqttd_metrics:inc('bytes/received', Size),
received(Data, rate_limit(Size, State#client_state{await_recv = false}));

L2,L3,L4这三行代码主要用于调试和metric。

2、socket 数据包解析

socket 二进制数据包的解析,主要是由emqttd_parser module进行处理,包括二进制协议的解析以及socket 粘包的处理。

  • message 由emqttd_parser module进行二进制数据协议的解析

解析成为mqtt_pakcet record 类型的数据结构。

3、mqtt packet 处理

emqtt中,mqtt packet的处理是由emqtt_protocol module完成,其入口函数为received/2:

 %% A Client can only send the CONNECT Packet once over a Network Connection.
-spec(received(mqtt_packet(), proto_state()) -> {ok, proto_state()} | {error, any()}).
received(Packet = ?PACKET(?CONNECT), State = #proto_state{connected = false}) ->
process(Packet, State#proto_state{connected = true}); received(?PACKET(?CONNECT), State = #proto_state{connected = true}) ->
{error, protocol_bad_connect, State}; %% Received other packets when CONNECT not arrived.
received(_Packet, State = #proto_state{connected = false}) ->
{error, protocol_not_connected, State}; received(Packet = ?PACKET(_Type), State) ->
trace(recv, Packet, State),
case validate_packet(Packet) of
ok ->
process(Packet, State);
{error, Reason} ->
{error, Reason, State}
end.

前三个子函数,主要处理"是否已经login"相关的packet,而最后一个子函数则是在login 之后,处理正常的packet。

在emqttd_protocol module 中,由入口函数received 做简单的处理之后,则交由本module 中的process/2 函数进行处理,并最后交由后续的实际业务module 进行处理。

  • mqtt packet 由emqttd_protocol module进行处理,并交由后续的module

综上,在emqtt中,message 基本的流向为:

  1. message进入到server后,首先由emqttd_client module进行处理
  2. message 由emqttd_parser module进行二进制数据协议的解析
  3. mqtt packet 由emqttd_protocol module进行处理,并交由后续的module
  4. 后续根据不同类型的packet,再做不同的处理

图示如下:

P5: message基本流向示意图

总结

需要?

emqtt 1 (初初初初稿)的更多相关文章

  1. 一个原生JS实现的不太成熟的贪吃蛇游戏

    一个初初初初级前端民工 主要是记录一下写过的东西,复习用 大佬们如果看到代码哪里不符合规范,或者有更好写法的,欢迎各位批评指正 十分感谢 实现一个贪吃蛇游戏需要几步? 1.有地图 2.有蛇 3.有食物 ...

  2. DICOM:DICOM标准学习路线图(初稿)

    题记: DICOM医学图像处理专栏撰写已有两个年头,积累了近百篇文章.起初只是用于记录自己科研.工作中遇到的疑难问题,专注于图像处理(主要是医学图像,这也正是专栏名称最初的由来):后来逐渐延伸到了DI ...

  3. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  4. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  5. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  6. 【初码干货】使用阿里云对Web开发中的资源文件进行CDN加速的深入研究和实践

    提示:阅读本文需提前了解的相关知识 1.阿里云(https://www.aliyun.com) 2.阿里云CDN(https://www.aliyun.com/product/cdn) 3.阿里云OS ...

  7. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  8. 【初码干货】在Window Server 2016中使用Web Deploy方式发布.NET Web应用的重新梳理

    在学习和工作的过程中,发现很多同事.朋友,在做.NET Web应用发布的时候,依然在走 生成-复制到服务器 这样的方式,稍微高级一点的,就是先发布到本地,再上传到服务器 这种方式不仅效率低下,而且不易 ...

  9. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

随机推荐

  1. U盘安装OS

    1. 老毛桃 2. 大白菜 3.

  2. neutron dhcp ha 实验

    4个节点(controller, network,2 compute nodes) 1.0   on the network node 1.1 set –I ‘s/start] on/#start\ ...

  3. mysql数据库优化课程---7、网站的搜索技术怎么选

    mysql数据库优化课程---7.网站的搜索技术怎么选 一.总结 一句话总结: 1.量很小(像小网站)---like2.量大一点()---标签3.量超级大(像百度)---搜索引擎 1.数据库中取一列比 ...

  4. php超级全局变量和魔术变量

    php超级全局变量和魔术变量 一.总结 一句话总结: 1.两者的书写形式非常不一样,超级全局变量是$_大写变量名 的形式,魔术变量是 __大写变量名的形式__ 2.两者的应用范围不一样,超级全局变量是 ...

  5. web自动化中的page object模式

    一. 原理 将页面的元素定位和元素行为封装成一个page类,实现页面对象和测试用例分离 类的属性:元素定位 类的行为:元素的操作 测试用例:调用所需页面对象中的行为,组成测试用例 二. 好处 1. 当 ...

  6. CC 攻击检测研究现状

    网络层ddos 是让去往银行的道路交通变得拥堵,无法使正真要去银行的人到达:常利用协议为网络层的,如tcp(利用三次握手的响应等待及电脑tcp 连接数限制)等应用层ddos 则是在到达银行后通过增办. ...

  7. mongDB网址

    http://www.cnblogs.com/huangxincheng/archive/2012/02/18/2356595.html

  8. Android性能优化系列总篇

    目前性能优化专题已完成以下部分: 性能优化总纲——性能问题及性能调优方式 性能优化第四篇——移动网络优化 性能优化第三篇——Java(Android)代码优化 性能优化第二篇——布局优化 性能优化第一 ...

  9. java学习网站推荐

    推荐大家一个好的java学习网站: http://www.programcreek.com/java-api-examples/index.php 可以找到api对应的开源项目使用的代码.

  10. android 删除SD卡或者手机的缓存图片和目录

    public static final String TEMP_PHOTO_FILE_NAME = "temp_photo.jpg"; private static String ...