前提
这里我只是根据我实际用的功能来实现MQTT协议,并没有把MQTT全部实现。接下来我会介绍我是怎么实现MQTT协议的,希望能给你帮助。
思路
首先介绍一下大致思路。 在头文件中定义
-
MQTT的结构体 这个结构体来保存一些缓冲区的指针,报文的类型,结果代码,错误代码等等。 -
各种报文的结构体 因为每个报文都不同,不同的位,格式有差异,所以我们需要根据每种报文定义结构体。 -
枚举各个报文的值 比如枚举出各个报文,用来区分报文。
用宏定义定义一些需要修改的值。
-
超时等待时间 比如客户端连接服务端,客户端需要等待服务端相应,但是客户端不能一直等待下去,所以我们需要定义一个超时等待时间。 -
与服务端连接保活时间 这个时间在不同的情景下是有差异,所以需要单独拎出来。 -
缓冲区的大小 根据需要传输的数据最大大小来设置缓冲区的大小
接下来从头文件开始介绍。
报文类型的枚举
在头文件中将MQTT协议中所以控制报文枚举出来。 注意下枚举的值必须要与MQTT协议中的值一一对应。
typedef enum
{
MQTT_CONNECT = 0x10U,
MQTT_CONNACK = 0x20U,
MQTT_PUBLISH = 0x30U,
MQTT_PUBACK = 0x40U,
MQTT_PUBREC = 0x50U,
MQTT_PUBREL = 0x60U,
MQTT_PUBCOMP = 0x70U,
MQTT_SUBSCRIBE = 0x82U,
MQTT_SUBACK = 0x90U,
MQTT_UNSUBSCRIBE = 0xA2U,
MQTT_UNSUBACK = 0xB0U,
MQTT_PINGREQ = 0xC0U,
MQTT_PINGRESP = 0xD0U,
MQTT_DISCONNECT = 0xE0U
}MessageType_t;
定义了一个新的枚举类型MessageType_t 。
数据类型的枚举
因为传输的数据有字符和实数,所以我们需要区分。 为什么实数的枚举值是-1 ,而字符的枚举值是1 ,我将在之后讲解。
typedef enum
{
NUM = -1,
CHAR = 1,
}DataType_t;
定义了一个新的枚举类型DataType_t 。
宏定义
正如上文提到的,定义了一些需要根据情景来修改的数值。
#define MQTT_MAX_TIMES_OUT (1000U)
#define MQTT_KEEP_ALIVE (300U)
#define MQTT_BUFF_SIZE (200U)
MQTT结构体
typedef struct
{
MessageType_t messageType;
char *sendBuff;
char *sendBuffPointNow;
char resultCode;
unsigned int remainLength;
void *returnData;
}MQTT_t;
说明一些需要注意的地方。
- 存储了报文的类型
MessageType_t 的变量messageType , - 存储指向数据发送缓冲区的指针
sendBuff ,该数据发送缓冲区的大小是用宏定义MQTT_BUFF_SIZE 定义的。 - 指向数据发送缓冲区当前位置的指针
sendBuffPointNow ,解释一下就是当我们往数据发送缓冲区写入X个字节后,该指针就会增长X个字节。 - 结果返回代码
resultCode ,一些报文是需要根据服务端响应的数据来判断状态的,比如CONNECT报文,当我们连接服务端的时候,需要服务端返回CONNACK报文,来指示客户端是否连接成功。其中resultCode 的初始值也用了一个宏定义定义 #define MQTT_RESULT_CODE_INIT (0x0F) - 指向服务端返回的报文结构体的指针
returnData ,举个例子,客户端连接服务端,服务端会返回一个CONNEACK报文,同时我们也定义一个与CONNACK对应的结构体s ,returnData 就是指向这个结构体s 。
各种报文的结构体
没啥可介绍,把报文中需要设置的位、需要发送的数据等等提取出来就可以。 这里我只贴上几个重要的结构体的定义。
typedef struct
{
unsigned char connectFlag;
unsigned short keepAliveTime;
const char *clientID;
const char *userName;
const char *password;
}MQTTConnectStruct_t;
typedef struct
{
char RETAIN;
char QoS;
char DUP;
unsigned short messageID;
const char *topic;
const char *payload;
}MQTTPublishStruct_t;
typedef struct
{
unsigned short messageID;
char QoS;
const char *payload;
}MQTTSubscribeStruct_t;
C语言实现MQTT协议(一)协议讲解
C语言实现MQTT协议(二)头文件介绍
C语言实现MQTT协议(三)源代码介绍及连接阿里云
|