接下来我讲解一下这个简单的客户端,其中,大体的流程如下:
大体的流程如图所示,在客户端启动之后,会启动线程,创建一个订阅客户端,它会监听消息的到达,在消息到达之后会触发相应的回调函数以对消息进行处理;后在启动一个线程,创建一个发送客户端,用来发送消息的,每次发送消息之前会判断是否要掉线,如CONNECT=0则会掉线,否则发送消息给topic01。
订阅客户端详解
-------
以下函数完成的是订阅的功能。 void *subClient(void *threadid) 过程大概如下:
第一步:声明客户端,并通过函数给其赋值;
MQTTClient client; MQTTClient_create(&client, ADDRESS, SUB_CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);第二步:设置连接MQTT服务器的选项;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;第三步:设置回调函数;
MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered); //相应的回调函数connlost,msgarrvd,delivered我的代码中都有第四步:使用客户端和连接选项连接服务器;
MQTTClient_connect(client, &conn_opts))第五步订阅话题;
MQTTClient_subscribe(client, TOPIC, QOS);第六步一直等待,知道输入'Q' 或'q';
do { ch = getchar(); } while(ch!='Q' && ch != 'q');第六步一直等待,直到输入'Q' 或'q';
do { ch = getchar(); } while(ch!='Q' && ch != 'q');第七步取消订阅;
MQTTClient_unsubscribe(client, TOPIC);第八步.断开客户端连接;
MQTTClient_disconnect(client, 10000);第九步.释放客户端使用的所有内存;
MQTTClient_destroy(&client); 至此,订阅客户端就结束了。一般订阅客户端的大体结构都是这样。不同的是回调函数的个性化上。
发送客户端详解
-------
以下函数完成的是发送的功能。
第一步:声明客户端,并通过函数给其赋值;
MQTTClient client; MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);第二步:设置连接MQTT服务器的选项;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;第三步:使用客户端和连接选项连接服务器;
MQTTClient_connect(client, &conn_opts)第四步设置发送消息的属性;
pubmsg.payload = PAYLOAD; pubmsg.payloadlen = strlen(PAYLOAD); pubmsg.qos = QOS; pubmsg.retained = 0;第五步循环发送消息;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);第六步一直等待,当CONNECT=0时退出该客户端;
第七步.断开客户端连接;
MQTTClient_disconnect(client, 10000);第八步.释放客户端使用的所有内存;
MQTTClient_destroy(&client);至此,发送客户端就结束了。一般的发送客户端大体结构也如此,但异步客户端可能有些许不同,无非就是设计回调函数,然后在连接,断开连接等时可以使用回调函数做一些操作而已,具体的可以自己研究。
为了让大家能够更深入了解,我把自己学到的一些函数和结构体大致在下面讲解了一下。
相关结构体
-----
定义:typedef void* MQTTClient;
含义:代表MQTT客户端的句柄。成功调用MQTTClient_create()后,可以得到有效的客户端句柄。
定义:
typedef struct { char struct_id[4];//结构体的识别序列,必须为MQTC int struct_version;//结构体版本 /** 在0,1,2,3,4,5中取值: 0-表示没有SSL选项且没有serverURIs; 1-表示没有serverURIs; 2-表示没有MQTTVersion 3-表示没有返回值; 4-表示没有二进制密码选项 */ int keepAliveInterval; /** 在这段时间内没有数据相关的消息时,客户端发送一个非常小的MQTT“ping”消息,服务器将会确认这个消息 */ int cleansession; /** 当cleansession为true时,会话状态信息在连接和断开连接时被丢弃。 将cleansession设置为false将保留会话状态信息 */ int reliable; /* 将该值设置为true意味着必须完成发布的消息(已收到确认),才能发送另一个消息 */ MQTTClient_willOptions* will; /* 如果程序不使用最后的意愿和遗嘱功能,请将此指针设置为NULL。 */ const char* username;//用户名 const char* password;//密码 int connectTimeout;//允许尝试连接的过时时间 int retryInterval;//尝试重连的时间 MQTTClient_SSLOptions* ssl; /* 如果程序不使用最后的ssl,请将此指针设置为NULL。 */ int serverURIcount; char* const* serverURIs; /* 连接服务器的url,以protocol:// host:port为格式 */ int MQTTVersion; /* MQTT的版本,MQTTVERSION_3_1(3),MQTTVERSION_3_1_1 (4) */ struct { const char* serverURI; int MQTTVersion; int sessionPresent; } returned; struct { int len; const void* data; } binarypwd; } MQTTClient_connectOptions;含义:用来设置MQTTClient的连接选项的结构体。
MQTTClient_message