MQTT协议的工作流程如下:

其实很简单,就是通过客户端向服务器发布订阅主题来实现信息的交互。这里我将用简单的代码实现客户端的功能。

MQTT服务器安装

这里我用的树莓派作为服务器,安装的服务器是mosquitto。
安装流程很简单

sudo apt-get update #获取更新
sudo apt-get install mosquitto #安装mosquitto服务器
mosquitto -v #启动mosquitto服务器

依次输入上面代码即可,当然,你也可以安装到其他地方,比如虚拟机,或者电脑都可以,下面这个网址有mosquitto在不同环境的安装包和教程
软件下载地址

电脑模拟抓包

服务器安装完成后,需要先分析以下客户端和服务器之间的通讯,先找电脑上装一个MQTT客户端软件,这里我装的是MQTT.fx,安装包网上有很多资源,可以自己去找,接下来打开软件,按照步骤输入以下内容,其中服务器默认端口是1883,所以一定要设置为1883。

然后打开wireshark,准备好了之后,点击MQTT.fx软件上的connect开始抓包,不会wireshark软件可参考我的一篇文章

wireshark抓包_yuansec的博客-CSDN博客
通过抓取的包,发现,MQTT协议是基于TCP/IP协议的,客户段连接服务器的动作,首先是tcp三次握手,接着发送连接请求命令。


继续抓包,新建一个发布,发送给服务器,这里使用的QoS0等级发送,可以看出,发送很简单,一条报文即可,解析出来的数据可以看出,这条报文包含了主题和内容


接着,新建一个订阅,抓取报文


最后,再次发布,可以打看到数据发送到了订阅,同时抓取的报文可以看到数据交互过程

代码实现

这里我在虚拟机实现客户端功能,linux环境
首先按照刚刚的步骤,先进行sock连接,进行tcp的三次握手

int connect_sock()
{   int sock;struct sockaddr_in aa;sock = socket(AF_INET, SOCK_STREAM, 0);if(sock == -1){printf("sock error\n");return -1;}aa.sin_family = AF_INET;aa.sin_port = htons(1883);aa.sin_addr.s_addr = inet_addr("192.168.0.10");if(connect(sock, (struct sockaddr *)&aa, sizeof(aa)) < 0){printf("connect error\n");return -1;}printf("connect with destination host...\n");return sock;
}

接着,MQTT连接请求,这里参照抓包的格式,直接定义好每一个字节

int connect_pub(int fd)
{char data[1024];data[0] = 0x10;data[1] = 14;data[2] = 0x00;data[3] = 0x04;data[4] = 'M';data[5] = 'Q';data[6] = 'T';data[7] = 'T';data[8] = 4;data[9] = 2;data[10] = 0x00;data[11] = 0x3c;data[12] = 0x00;data[13] = 0x02;data[14] = 'f';data[15] = 'e';int sum = send(fd, data, 16, 0);if(sum < 0){printf("send error\n");return -1;}printf("connect_pub send sum = %d\n",sum);return 0;
}

接着就是建立订阅连接

int connect_sub(int fd, char *topic)
{char data[1024];int i;data[0] = 0x82;data[2] = 0x00;data[3] = 0x03;int len = strlen(topic);data[4] = len/256;data[5] = len%256;for(i = 0; i < len; i++)data[6 + i] = topic[i];data[6 + len] = 0x00;data[1] = 5 + len;int sum = send(fd, data, 7 + len, 0);if(sum < 0){printf("send error\n");return -1;}printf("connect_sub send sum = %d\n",sum);return 0;
}

建立好订阅连接后,就可以发布内容了,同时创建一个线程,接收服务器发回来的数据

int pub(int fd, char *topic, char *str)
{char data[1024];int i;data[0] = 0x30;int t_len = strlen(topic);data[2] = t_len/256;data[3] = t_len%256;for(i = 0; i < t_len; i++)data[4 + i] = topic[i];int s_len = strlen(str);for(i = 0; i < s_len; i++)data[4 + t_len + i] = str[i];data[1] = 2 + t_len + s_len;   int sum = send(fd, data, 4 + t_len + s_len, 0);if(sum < 0){printf("send error\n");return -1;}//printf("pub sum = %d\n",sum);return 0;
}struct msg
{int fd;char *topic;
};
void *sub_rev(struct msg *msg_sub)
{char data[1024];char str[1024];while(1){int num = recv(msg_sub->fd, data, 1024, 0);if(num < 0){printf("recv error\n");return 0;}if(num > 0){if(data[0] == 0x30){int len = data[2]*256 + data[3];if(strncmp(data + 4, msg_sub->topic, len) == 0){strncpy(str, data + 4 + len, num - 4 - len);printf("recv data:%s\n", str);memset(data, '\0', strlen(data));memset(str, '\0', strlen(str));}}}}
}

实现效果

这里主题名固定了,实际应用的话可以自己定义主题,可以看到,效果实现了

完整代码

最后还有一个断开连接的代码,这里我就不去完成了,原理是一样的

#include<stdio.h>
#include<sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>int connect_sock()
{   int sock;struct sockaddr_in aa;sock = socket(AF_INET, SOCK_STREAM, 0);if(sock == -1){printf("sock error\n");return -1;}aa.sin_family = AF_INET;aa.sin_port = htons(1883);aa.sin_addr.s_addr = inet_addr("192.168.0.10");if(connect(sock, (struct sockaddr *)&aa, sizeof(aa)) < 0){printf("connect error\n");return -1;}printf("connect with destination host...\n");return sock;
}int connect_pub(int fd)
{char data[1024];data[0] = 0x10;data[1] = 14;data[2] = 0x00;data[3] = 0x04;data[4] = 'M';data[5] = 'Q';data[6] = 'T';data[7] = 'T';data[8] = 4;data[9] = 2;data[10] = 0x00;data[11] = 0x3c;data[12] = 0x00;data[13] = 0x02;data[14] = 'f';data[15] = 'e';int sum = send(fd, data, 16, 0);if(sum < 0){printf("send error\n");return -1;}printf("connect_pub send sum = %d\n",sum);return 0;
}
int connect_sub(int fd, char *topic)
{char data[1024];int i;data[0] = 0x82;data[2] = 0x00;data[3] = 0x03;int len = strlen(topic);data[4] = len/256;data[5] = len%256;for(i = 0; i < len; i++)data[6 + i] = topic[i];data[6 + len] = 0x00;data[1] = 5 + len;int sum = send(fd, data, 7 + len, 0);if(sum < 0){printf("send error\n");return -1;}printf("connect_sub send sum = %d\n",sum);return 0;
}
int pub(int fd, char *topic, char *str)
{char data[1024];int i;data[0] = 0x30;int t_len = strlen(topic);data[2] = t_len/256;data[3] = t_len%256;for(i = 0; i < t_len; i++)data[4 + i] = topic[i];int s_len = strlen(str);for(i = 0; i < s_len; i++)data[4 + t_len + i] = str[i];data[1] = 2 + t_len + s_len;   int sum = send(fd, data, 4 + t_len + s_len, 0);if(sum < 0){printf("send error\n");return -1;}//printf("pub sum = %d\n",sum);return 0;
}struct msg
{int fd;char *topic;
};
void *sub_rev(struct msg *msg_sub)
{char data[1024];char str[1024];while(1){int num = recv(msg_sub->fd, data, 1024, 0);if(num < 0){printf("recv error\n");return 0;}if(num > 0){if(data[0] == 0x30){int len = data[2]*256 + data[3];if(strncmp(data + 4, msg_sub->topic, len) == 0){strncpy(str, data + 4 + len, num - 4 - len);printf("recv data:%s\n", str);memset(data, '\0', strlen(data));memset(str, '\0', strlen(str));}}}}
}int main()
{int sock;  char topic[1024] = "test";char str[1024];sock = connect_sock();if(sock < 0){printf("connect_sock error\n");return 0;}if(connect_pub(sock) < 0){printf("connect_pub error\n");return 0;}if(connect_sub(sock, topic) < 0){printf("connect_sub error\n");return 0;}pthread_t sub_id;struct msg sub_msg;sub_msg.fd = sock;sub_msg.topic = topic;pthread_create(&sub_id, NULL, (void*)*sub_rev, &sub_msg);usleep(100 * 1000);while(1){printf("please input message:");fgets(str, 1024, stdin);pub(sock, topic, str);memset(str, '\0', strlen(str));usleep(100 * 1000);}close(sock);}

简单代码实现MQTT客户端功能相关推荐

  1. 在Windows系统中通过简单代码实现一键截图功能

    1.在桌面上新建一个文本文档,如下图 2.打开文本文档,输入以下代码, start snippingtool 3.输入后并保存,并将文本文档改名为截图,其文本文档后缀名改为bat 4. 点击就会出现如 ...

  2. mongoose搭建mqtt客户端

    这几天从 github mongoose 下载了 mongoose 的最新代码,然后想用这份代码搭建 mqtt 客户端,然而在编译的时候出现了一些错误,记录如下: 因为这个是源码是 mongoose. ...

  3. 【微信小程序控制硬件②】 开始微信小程序之旅,导入小程序Mqtt客户端源码,实现简单的验证和通讯于服务器.(附带源码)

    文章目录 一.前言: 二.注册微信小程序: 三.本博文连接和微信物联有何区别: 四.微信小程序`MQTT`客户端源码导入注意事项: 五.下载: 微信物联网生态主要分在微信硬件开发平台与腾讯物联开发平台 ...

  4. Tencent APIJSON 零代码、全功能、强安全 ORM 库 后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构

    项目介绍 零代码.全功能.强安全 ORM 库 后端接口和文档零代码,前端(客户端) 定制返回 JSON 的数据和结构. A JSON Transmission Protocol and an ORM ...

  5. mqtt linux 编译,MQTT客户端代码X64位Ubuntu环境编译+测试实践小结

    https://cloud.baidu.com/doc/IOT/IoTdownload.html#.E4.B8.8B.E8.BD.BDMQTT.E7.9B.B8.E5.85.B3 下载MQTT相关: ...

  6. C#摄像头实现拍照功能的简单代码示例

    C#摄像头实现拍照功能的简单代码示例 2009-11-20  来自:网上整理字体大小:[大中小] ·摘要:这里将介绍一个C#摄像头实现拍照功能的简单代码示例,代码虽然不短,但是基本上实现了相对应的功能 ...

  7. 简单的计算机程序代码,优秀程序员通过简单代码,窥探电脑编程中强大的数组操作功能...

    优秀程序员通过简单代码,窥探电脑编程中强大的数组操作功能.编程语言中,数组是一个非常重要的概念,也是一种很常用的类型.本文中通过javascript语言的代码实例,展现编程中数组的魅力.在javasc ...

  8. java怎么实现复制粘贴的操作,java简单实现复制 粘贴 剪切功能代码分享

    废话不多说,直接上代码,小伙伴们仔细看下注释吧. /*简单的复制 剪切 粘贴 功能 操作: 复制测试: 输入文本选择文本,点击复制,然后将光标放在右边的TextArea,点击粘贴 剪切测试:输入文本选 ...

  9. 斗兽棋 java_AnimalGame 一个简单的斗兽棋代码实现,基本功能 现了,支持人人对战 JavaScript 238万源代码下载- www.pudn.com...

    文件名称: AnimalGame下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 2257 KB 上传时间: 2015-01-26 下载次数: 0 提 供 者: 盛 ...

最新文章

  1. linux 安装redis4.0.6,Redis(4.0.6)在Linux(CentOS7)下的安装
  2. maven 添加数据库驱动
  3. 灯光插件_Light Kit Pro 3灯光插件
  4. VTK:小部件之LineWidget2
  5. oracle sqlplus conn 远程连接
  6. 01_SQlite数据库简介
  7. 关于HTML的面试题-html5/css3篇
  8. 你见过在地铁里哭的人吗?扎心了老铁!!
  9. 解决pytorch二分类任务交叉熵损失函数CrossEntropyLoss报错:IndexError: Target 1 is out of bounds.
  10. CF1062E Company
  11. 这就是华为Mate 30 Pro真机了,价格或许要高攀不起了?
  12. 用汉堡包的方式评价一下自己的合作伙伴
  13. linux 文件安装大全,linux 文件包安装大全
  14. vFORUM 2018,开启多云未来
  15. UEFI规范实现EDKII项目学习笔记绪论[0]
  16. Dapper使用技巧和基础CRUD
  17. 论实力和智慧,美的微晶冰箱有点东西!
  18. 爬虫学习笔记(十八)—— 点触验证码:超级鹰、12306自动登录
  19. 服务器灾备解决方案--两地三中心(图文详解)
  20. 关于华为交换机bpdu enable. ntdp enable. ndp enable解析

热门文章

  1. 删除数组中的某个元素的方法
  2. Android ADB命令?这一次我再也不死记了!
  3. 回复 C++中如何将Int类型转换为String类型?
  4. 读书笔记 --- 人人都是产品经理v2
  5. 欧盟站婴儿奶瓶EN14350测试项目
  6. 一张图让你了解Storm的DRPC实现原理
  7. 【无标题】Python __all__=[]作用
  8. NetGear_DGN2200 命令执行漏洞 CVE-2017-6077
  9. Windows Server 虚拟机安装
  10. I2C协议和驱动框架分析(二)