使用网络调试助手连接EMQ服务器

一、使用MQTT协议与服务器建立连接

1.在图纸中的位置输入EMQ服务器地址与EMQ服务器的端口。在这里插入图片描述
2.接下来我们来看一下MQTT协议中的CONNECT报文、
在这里插入图片描述
(1)固定报头

在这里插入图片描述
byte1为0x10,表示向服务器端发送的为CONNECT报文,剩余长度值后等学到再继续介绍。我们先用##来代替。
那么现在CONNECT报文的前两个字节为 01 ##

(2)可变报头
CONNECT的可变报头按顺序有以下四个字段:协议名、协议级别、连接标志、保持连接。

a)协议名
在这里插入图片描述
按照MQTT文档所给出的表格,把他们表示为16进制为:
00 04 4D 51 54 54

b)协议级别
在这里插入图片描述
现在所用的MQTT协议版本为3.1.1,那么协议级别的值为4(0x40),其他的协议级别,在对应的协议文档中应该都会给出。那么第七位字节为 04

c) 连接标志
在这里插入图片描述
在EMQ服务器的设置中,我启动了emqx_auth_mysql,开启了认证。所以登录的时候是需要用户名与密码的,服务质量QoS一般都设为0。清理会话标志位,一般也会设置为1(等我理解了如何使用后在来详细介绍)。根据自己的需求,设置此字节为 11000010转换为十六进制对应 C2

d) 保持连接

在这里插入图片描述
保持连接是一个以秒为单位的时间间隔,表示为一个16位的字。我们把它设置为100秒。那么这两位为 00 64

可变报头这样前期我们就基本固定为:00 04 4D 51 54 54 04 C2 00 64

(3) 有效负荷

可变报头中的连接标志决定了有效负荷中所要包含的信息,如果包含信息的话,则必须按照以下顺序填写:客户端标识符、遗嘱主题、遗嘱消息、用户名、密码。
1.首先我们设置客户标识符:
举个例子:当把客户标识符设为sun时,会在EMQ客户端出现
在这里插入图片描述

这种标识,该设备的客户端ID就被设置为了sun方便以后查找使用。那么此时客户端ID的十六进制表示为 73 75 6E,接下来在这三个字节的前面加上客户端ID的字节长度占用两字节:00 03,组合一下就是00 03 73 75 6E

由于没有设置遗嘱相关,所以我们就跳过遗嘱相关信息,直接填写用户的相关信息。应为在之前已配置好并启动了emqx_auth_mysql插件,在数据库中存入了一个user。其用户名为222,密码为111111,所以我们所要填入的就是这两个信息。
首先是用户名,将222转变为十六进制形式,注意这里的222并不是十进制的222而是字符串,转换的时候要留意,变为 32 32 32,同样在前面加上两个字节表示长度 00 03 ,组合下,变为:00 03 32 32 32
接下来是用户密码,同用户名一样的处理变为:00 06 31 31 31 31 31 31

当这些都转化完成后,我们要开始连接我们的服务器了,把上面的所有转化好的十六进制字节合并起来,变为:10 ## 00 04 4D 51 54 54 04 C2 00 64 00 03 73 75 6E 00 03 32 32 32 00 06 31 31 31 31 31 31
就剩下一个##是位置的了,先用最笨的方法,数一下##之后共有多少字节,那么##就是多少。后面会学到使用算法来计算剩余长度,所以就先数一下把。数完以后,我们这里是一共28个字节,所以 ## = 1C 。那么完整版就为:10 1C 00 04 4D 51 54 54 04 C2 00 64 00 03 73 75 6E 00 03 32 32 32 00 06 31 31 31 31 31 31
在这里插入图片描述
在网络助手中在下面选择HEX形式发送,把配置好的CONNECT报文复制到发送框,发送之后会接受到服务器返回的 20 02 00 00,此时就表示我们成功连接到EMQ服务器啦!在EMQ的客户端页面就可以查看到我们的设备已经上线了。

3.之前在做实验的时候,用到过中移物联OneNET,终端设备是通过EDP协议与OneNET建立连接的。就试着模仿EDP协议来写了一个简单的MQTT协议,来实现基本的通讯。下面是MQTT连接报文的C语言实现:

/*************** 动态申请内存 *************************/
#define MQTT_MALLOC_BUFF			malloc
#define MQTT_FREE_BUFF				free
/*************** 高低位先行 *************************/
#define MSB(A)							(uint8)((A & 0xFF00) >> 8)
#define LSB(A)							(uint8)(A & 0x00FF)
typedef struct Buffer
{
	uint8	*	_data;		//协议数据
	uint32	_len;		//写入的数据长度
	uint32	_size;		//缓存总大小
	uint8		_memFlag;	//内存使用的方案:0-未分配	1-使用的动态分配		2-使用的固定内存

} MQTT_PACKET_STRUCTURE;
/**
 *  函数名: MQTT_NewBuff
 *  作用  : 申请内存
 *  参数  : MQTT_Packet:包体结构
 *          size: 所要分配的内存大小
 */

void MQTT_NewBuff(MQTT_PACKET_STRUCTURE *MQTT_Packet,uint32 size)
{
    uint32 i = 0;
    if(MQTT_Packet->_data == NULL)
    {
        MQTT_Packet->_memFlag = MEM_FLAG_ALLOC;
        // 分配内存,MALLOCK返回值为所分配内存的开始位置的指针
        MQTT_Packet->_data = (uint8 *)MQTT_MALLOC_BUFF(size);
        if(MQTT_Packet->_data != NULL)
        {
            // 内存分配成功
            MQTT_Packet->_len = 0;
            MQTT_Packet->_size = size;
            for (i = 0; i < size; i++)
            {
                // 清空数据
                MQTT_Packet->_data[i] = 0;
            }
        }
    }
    else
    {
        // 使用全局变量或者局部变量来分配内存
        MQTT_Packet->_memFlag = MEM_FLAG_STATIC;
        for(i = 0; i < MQTT_Packet->_size; i++)
        {
            MQTT_Packet->_data[i] = 0;
        }
        MQTT_Packet->_len = 0;
        if(MQTT_Packet->_size < size)
        {
            // 如果所给的内存小于数据内存 则分配失败
            MQTT_Packet->_data = NULL;
        }
    }
}

/**
 *  函数名: MQTT_FreeBuff
 *  作用  : 释放内存
 *  参数  : MQTT_Packet:包体结构
 *
 */
void MQTT_FreeBuff(MQTT_PACKET_STRUCTURE *MQTT_Packet)
{
  MQTT_FREE_BUFF(MQTT_Packet->_data);
  // 重置包体结构
  MQTT_Packet->_data = NULL;
  MQTT_Packet->_len = 0;
  MQTT_Packet->_size = 0;
  MQTT_Packet->_memFlag = MEM_FLAG_NULL;
}

uint8 MQTT_Connect(const int8 * user_name,const int8 * password,uint16 keep_time,MQTT_PACKET_STRUCTURE * MQTT_Packet)
{
    // ClientID设置为与用户名相同
    const int8 * ClientID = user_name;
    uint8 ClientID_len = strlen(user_name);

    // 用户名称暂时为10
    uint8 user_name_len = strlen(user_name);

    // 密码长度为36
    uint8 password_len = strlen(password);
    // 80足够
    MQTT_NewBuff(MQTT_Packet,80);
    if(MQTT_Packet->_data == NULL)
    {
        // 内存分配失败
        printf("内存分配失败!\n");
        return 0;
    }

    /* byte0: 消息类型 */
    MQTT_Packet->_data[0] = CONNECT;
    MQTT_Packet->_len++;

    /* byte1: 剩余消息长度 */
    // 16 = 10 + 2 + 2 + 2  (10个固定长度,2表示ClientID,user_name,password长度表示位)
    MQTT_Packet->_data[1] = 16 + ClientID_len + user_name_len + password_len;
    MQTT_Packet->_len++;

    /* byte2-7: 协议描述 */
    MQTT_Packet->_data[2] = 0;
    MQTT_Packet->_data[3] = 4;
    strncat((int8 *)MQTT_Packet->_data + 4,"MQTT",4);
    MQTT_Packet->_len += 6;

    /* byte8: 协议级别 */
    MQTT_Packet->_data[8] = 4;
    MQTT_Packet->_len++;

    /* byte9: 连接标志 */
    MQTT_Packet->_data[9] = 0xC0;  // 保留会话(没有遗嘱,存在用户名与密码消息)
    MQTT_Packet->_len++;

    /* byte10-11: 保持连接时间 */
    MQTT_Packet->_data[10] = MSB(keep_time);
    MQTT_Packet->_data[11] = LSB(keep_time);
    MQTT_Packet->_len += 2;

    /* ClientID */
    MQTT_Packet->_data[12] = MSB(ClientID_len);
    MQTT_Packet->_data[13] = LSB(ClientID_len);
    MQTT_Packet->_len += 2;
    strncat((int8 *)MQTT_Packet->_data + 14,ClientID,ClientID_len);
    MQTT_Packet->_len += ClientID_len;

    /* user_name */
    MQTT_Packet->_data[14 + ClientID_len] = MSB(user_name_len);
    MQTT_Packet->_data[15 + ClientID_len] = LSB(user_name_len);
    MQTT_Packet->_len += 2;
    strncat((int8 *)MQTT_Packet->_data + 16 + ClientID_len,user_name,user_name_len);
    MQTT_Packet->_len += user_name_len;

    /* password */
    MQTT_Packet->_data[16 + ClientID_len + user_name_len] = MSB(password_len);
    MQTT_Packet->_data[17 + ClientID_len + user_name_len] = LSB(password_len);
    MQTT_Packet->_len += 2;
    strncat((int8 *)MQTT_Packet->_data + 18 + ClientID_len + user_name_len,password,password_len);
    MQTT_Packet->_len += password_len;

    return 1;


}

最后放上这个网络调试助手的下载地址吧
http://free.cmsoft.cn/download/cmsoft/netassist.zip

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值