女生做网站编辑怎么样网站建设济南
女生做网站编辑怎么样,网站建设济南,电影网站空间配置,c2c交易平台下载1、前言
前面完成了winform版#xff0c;wpf版#xff0c;为什么要搞个cmd版#xff0c;因为前面介绍了mqtt的报文结构#xff0c;重点分析了【连接报文】#xff0c;【订阅报文】#xff0c;【发布报文】#xff0c;这节就要就看看实际报文是怎么组装的#xff0c;这…1、前言
前面完成了winform版wpf版为什么要搞个cmd版因为前面介绍了mqtt的报文结构重点分析了【连接报文】【订阅报文】【发布报文】这节就要就看看实际报文是怎么组装的这也是之前详细每个报文的结构含义的目的使用mqttnet这个组件实现mqtt通信是直接应用不涉及到底层报文的结构内容用户是看不到报文内容的这节的目的就是为加深理解而干的。这节不安装任何mqtt的组件而是直接使用socket的原始方式通信。
2、报文回顾
一共有14个报文如下图 可以去看看3个报文的详细介绍什么固定报头可变报头有效载荷这些东东
C#MQTT编程03--连接报文
C#MQTT编程04--订阅报文
C#MQTT编程05--发布报文
总结出来就是这样的
连接报文是客户端发1服务器回2
订阅报文是客户端发8服务器回9
发布报文是客户端发3服务器回4
心跳报文是客户端发12服务器回13。
3、开始卷
1、创建项目方案 2、编写连接报文 完整的连接代码
/// summary
/// 连接
/// /summary
static void Connection()
{// MQTT不支持UDPsocket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socket.Connect(127.0.0.1, 1869);//连接报文Listbyte connBytes new Listbyte();#region 第一部分,固定报头// 第0个字节固定报头Listbyte headerBytes new Listbyte{14 //表示连接请求 消息类型 };//第1个字节剩余字节长度//需要后面计算得到#endregion#region 第二部分可变报头 // 第23个字节协议名称MQTT的字节长度Listbyte bodyBytes new Listbyte();string protocolName MQTT;byte[] pnameBytes Encoding.ASCII.GetBytes(protocolName);//得到“MQTT”的字节数组 bodyBytes.Add((byte)(pnameBytes.Length / 256 % 256));//高4位bodyBytes.Add((byte)(pnameBytes.Length % 256));//低4位// 第4567个字节协议名称bodyBytes.AddRange(pnameBytes);// 第8个字节 协议版本bodyBytes.Add(0x04);// 第9个字节 负载是否需要用户名密码等设置byte flagByte 0;flagByte | 128; // 1 0 0 0 0 0 0 0 128 // 需要用户 flagByte | 64; // 0 1 0 0 0 0 0 0 64 // 需要密码 flagByte | 2; // CleanSessionbodyBytes.Add(flagByte);// 第1011个字节 Keep Alive保持连接的时间高位在前低位在后int seconds 100; // 秒为单位bodyBytes.Add((byte)(seconds / 256 % 256));bodyBytes.Add((byte)(seconds % 256));#endregion#region 第三部分载荷Listbyte loadBytes new Listbyte();// 第1213个字节ClientID字符长度string clientID x2;byte[] ciBytes Encoding.ASCII.GetBytes(clientID);loadBytes.Add((byte)(ciBytes.Length / 256 % 256));loadBytes.Add((byte)(ciBytes.Length % 256));// 第141151617个字节ClientIDloadBytes.AddRange(ciBytes);// 第1819个字节用户名长度string username boss;byte[] unBytes Encoding.ASCII.GetBytes(username);loadBytes.Add((byte)(unBytes.Length / 256 % 256));loadBytes.Add((byte)(unBytes.Length % 256));// 第2021222324个字节用户名loadBytes.AddRange(unBytes);// 第2526个字节密码长度string pwd 1234;byte[] pwdBytes Encoding.ASCII.GetBytes(pwd);loadBytes.Add((byte)(pwdBytes.Length / 256 % 256));loadBytes.Add((byte)(pwdBytes.Length % 256));// 第2728293031个字节密码loadBytes.AddRange(pwdBytes);#endregion//第1个字节剩余字节长度从第 2 个字节开始。headerBytes.Add((byte)(bodyBytes.Count loadBytes.Count));//组装成报文connBytes.AddRange(headerBytes);connBytes.AddRange(bodyBytes);connBytes.AddRange(loadBytes);//发送报文socket.Send(connBytes.ToArray());// 异步处理开始心跳Task.Run(async () {byte[] pingBytes new byte[2] { 12 4, 0 };//心跳的字节报文是固定的while (true){Console.WriteLine(心跳时间 DateTime.Now.ToString());await Task.Delay(1000);//等待1秒socket.Send(pingBytes);}});//异步处理服务器返回的报文Task.Run(() {//1请求连接 (C-S)//2连接确认 (S-C)//3发布消息 (Both)//4发布收到确认 (QoS 0)//5发布确认收到//6发布释放//7发布完成 (QoS 2)//8订阅请求 (C-S)//9订阅请求确认 (S-C)//10取消订阅请求 (C-S)//11取消订阅请求确认 (S-C)//12心跳请求 (C-S)//13心跳确认 (S-C)//14客户端断开连接 (C-S)byte[] respBytes new byte[1]; //接收MQTT报文类型报文类型占1个字节//连接成功MQTT报文类型CONNACK服务器返回2即0000 0010高低位交换位置就是返回0 0 1 0 0 0 0 0 转成10进制就是32//发布成功MQTT报文类型PUBACK 服务器返回4即0000 0100高低位交换位置就是返回0 1 0 0 0 0 0 0 转成10进制就是64//订阅成功MQTT报文类型SUBACK 服务器返回9即0000 1001高低位交换位置就是返回1 0 0 1 0 0 0 0 转成10进制就是144//心跳成功MQTT报文类型PINGRESP服务器返回13即0000 1101高低位交换位置就是返回1 1 0 1 0 0 0 0 转成10进制就是208while (true)//循环接收{try{socket.Receive(respBytes, 0, 1, SocketFlags.None);int firstValue Convert.ToInt32(respBytes[0]);//Console.WriteLine(第一个字节 firstValue);//根据报文类型进行处理switch (firstValue){case 32:Console.WriteLine(连接成功!);break;case 64:Console.WriteLine(发布成功!);break;case 144:Console.WriteLine(订阅成功!);break;case 208:Console.WriteLine(心跳成功!);break;}}catch (Exception ex){Console.WriteLine(出错了 ex.Message);}}});
}
特别注意这里的处理 //连接成功MQTT报文类型CONNACK服务器返回2即0000 0010高低位交换位置就是返回0 0 1 0 0 0 0 0 转成10进制就是32//发布成功MQTT报文类型PUBACK 服务器返回4即0000 0100高低位交换位置就是返回0 1 0 0 0 0 0 0 转成10进制就是64//订阅成功MQTT报文类型SUBACK 服务器返回9即0000 1001高低位交换位置就是返回1 0 0 1 0 0 0 0 转成10进制就是144//心跳成功MQTT报文类型PINGRESP服务器返回13即0000 1101高低位交换位置就是返回1 1 0 1 0 0 0 0 转成10进制就是208
心跳的处理它的作用是不断地发送命令以证明客户端存在 测试连接
先把前面的wpf版程序运行启动服务器启动客户端连接服务器 再启动本项目程序可以看到连接成功心跳也成功。 3、编写订阅报文
这里设置的qos级别是1Qos级别-》 0最多一次的传输1至少一次的传输、至多无限次2有且仅有一次的传输 完整代码 /// summary/// 订阅/// /summary/// param nametopics主题列表/paramstatic void Subscription(Liststring topics){Listbyte headerBytes new Listbyte();Listbyte bodyBytes new Listbyte();//第0个字节报文类型10000010byte msgType 8 4; // 1000 0000 headerBytes.Add((byte)(msgType | 2));//第1个字节剩余字节长度等后面计算获取后再添加//第23个字节Package Identifier的长度表示报文的标识int pi random.Next(0, 1000); // Package Identifier的具体值bodyBytes.Add((byte)(pi / 256 % 256));//高位bodyBytes.Add((byte)(pi % 256));//低位//遍历所有主题foreach (var item in topics){//第89个字节topic字符长度byte[] itemBytes Encoding.UTF8.GetBytes(item);bodyBytes.Add((byte)(itemBytes.Length / 256 % 256));bodyBytes.Add((byte)(itemBytes.Length % 256));//第101112131416个字节topic字符内容bodyBytes.AddRange(itemBytes);//第17个字节Qos级别-》 0最多一次的传输1至少一次的传输、至多无限次2有且仅有一次的传输bodyBytes.Add(0x01);}//第1个字节剩余字节长度从第 2 个字节开始。headerBytes.Add((byte)bodyBytes.Count);//组成报文headerBytes.AddRange(bodyBytes);//发送报文socket.Send(headerBytes.ToArray());//接收服务器回应的报文 //byte[] respBytes new byte[5];//socket.Receive(respBytes, 0, 5, SocketFlags.None);//var objSub respBytes; }
测试订阅
先让wpf客户端订阅一个主题“shanghai订阅成功 再看本项目程序订阅主题”shanghai,可以看到订阅成功 4、编写发布报文 完整代码注释详情 /// summary/// 发布消息服务级别(Qos1)/// /summarystatic void Publish_Qos1(){#region 方法1Listbyte headerBytes new Listbyte();//报文类型byte msgType 3 4; // 1000 0000 headerBytes.Add((byte)(msgType | 2)); // QoS-0低4位全为1Listbyte bodyBytes new Listbyte();string topic shanghai;string msg hello9098;// 添加主题长度byte[] topicBytes Encoding.UTF8.GetBytes(topic);bodyBytes.Add((byte)(topicBytes.Length / 256 % 256));bodyBytes.Add((byte)(topicBytes.Length % 256));// 添加主题内容bodyBytes.AddRange(topicBytes);// 必须添加Package Identifier只包括它的字节长度int pi random.Next(0, 1000); // Package Identifier//Console.WriteLine(pi);bodyBytes.Add((byte)(pi / 256 % 256));bodyBytes.Add((byte)(pi % 256));// 添加消息长度 byte[] msgBytes Encoding.UTF8.GetBytes(msg);bodyBytes.Add((byte)(msgBytes.Length / 256 % 256));bodyBytes.Add((byte)(msgBytes.Length % 256));// 添加消息内容bodyBytes.AddRange(msgBytes);//添加第1个字节剩余字节长度headerBytes.Add((byte)bodyBytes.Count);// 组装头 headerBytes.AddRange(bodyBytes);//发送消息socket.Send(headerBytes.ToArray());#endregion //#region 方法2//string topic shanghai;//string msg hello9098;//int pi random.Next(0, 1000); // Package Identifier//Listbyte topicbytes new Listbyte();//byte[] topicArray Encoding.UTF8.GetBytes(topic);//byte[] payloadArray Encoding.UTF8.GetBytes(msg);//topicbytes.Add((byte)((int)topicArray.Length / 256));//topicbytes.Add((byte)((int)topicArray.Length % 256));//topicbytes.AddRange(topicArray);//byte[] id new byte[] { (byte)(pi / 256 % 256), (byte)(pi % 256) };//byte[] bufferLen new byte[] { (byte)(topicbytes.Count payloadArray.Length id.Length) };//using (MemoryStream memoryStream new MemoryStream())//{// memoryStream.WriteByte((3 4) | 2 | 1);// 写入消息类型(QoS-1)// memoryStream.Write(bufferLen, 0, (int)bufferLen.Length);// 写入后续报文长度// memoryStream.Write(topicbytes.ToArray(), 0, (int)topicbytes.Count);// 写入Topic字节// memoryStream.Write(id.ToArray(), 0, (int)id.Length);// 写入Package Identifier字节// memoryStream.Write(payloadArray.ToArray(), 0, (int)payloadArray.Length);// 写入消息// byte[] sendArray memoryStream.ToArray();// socket.Send(sendArray);//}接收服务器回应的报文 //byte[] respBytes new byte[4];//socket.Receive(respBytes, 0, 4, SocketFlags.None);//var objSub respBytes;//#endregion }
测试发布 前面的c1订阅了主题“shanghai现在的x2客户端向shanghai主题发布一个消息看看c1能不能收到 最后全部完整代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;namespace MQTTNETClientCMD
{internal class Program{static Socket socket;//socket对象static Random random new Random();//随机数用于产生package identifierstatic Liststring topic new Liststring { shanghai };//主题static void Main(string[] args){Console.WriteLine(Hello MQTT!);Connection();//连接 Subscription(topic);//订阅Publish_Qos1();// 发布Qos1Console.ReadKey();}/// summary/// 连接/// /summarystatic void Connection(){// MQTT不支持UDPsocket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);socket.Connect(127.0.0.1, 1869);//连接报文Listbyte connBytes new Listbyte();#region 第一部分,固定报头// 第0个字节固定报头Listbyte headerBytes new Listbyte{14 //表示连接请求 消息类型 };//第1个字节剩余字节长度//需要后面计算得到#endregion#region 第二部分可变报头 // 第23个字节协议名称MQTT的字节长度Listbyte bodyBytes new Listbyte();string protocolName MQTT;byte[] pnameBytes Encoding.ASCII.GetBytes(protocolName);//得到“MQTT”的字节数组 bodyBytes.Add((byte)(pnameBytes.Length / 256 % 256));//高4位bodyBytes.Add((byte)(pnameBytes.Length % 256));//低4位// 第4567个字节协议名称bodyBytes.AddRange(pnameBytes);// 第8个字节 协议版本bodyBytes.Add(0x04);// 第9个字节 负载是否需要用户名密码等设置byte flagByte 0;flagByte | 128; // 1 0 0 0 0 0 0 0 128 // 需要用户 flagByte | 64; // 0 1 0 0 0 0 0 0 64 // 需要密码 flagByte | 2; // CleanSessionbodyBytes.Add(flagByte);// 第1011个字节 Keep Alive保持连接的时间高位在前低位在后int seconds 100; // 秒为单位bodyBytes.Add((byte)(seconds / 256 % 256));bodyBytes.Add((byte)(seconds % 256));#endregion#region 第三部分载荷Listbyte loadBytes new Listbyte();// 第1213个字节ClientID字符长度string clientID x2;byte[] ciBytes Encoding.ASCII.GetBytes(clientID);loadBytes.Add((byte)(ciBytes.Length / 256 % 256));loadBytes.Add((byte)(ciBytes.Length % 256));// 第141151617个字节ClientIDloadBytes.AddRange(ciBytes);// 第1819个字节用户名长度string username boss;byte[] unBytes Encoding.ASCII.GetBytes(username);loadBytes.Add((byte)(unBytes.Length / 256 % 256));loadBytes.Add((byte)(unBytes.Length % 256));// 第2021222324个字节用户名loadBytes.AddRange(unBytes);// 第2526个字节密码长度string pwd 1234;byte[] pwdBytes Encoding.ASCII.GetBytes(pwd);loadBytes.Add((byte)(pwdBytes.Length / 256 % 256));loadBytes.Add((byte)(pwdBytes.Length % 256));// 第2728293031个字节密码loadBytes.AddRange(pwdBytes);#endregion//第1个字节剩余字节长度从第 2 个字节开始。headerBytes.Add((byte)(bodyBytes.Count loadBytes.Count));//组装成报文connBytes.AddRange(headerBytes);connBytes.AddRange(bodyBytes);connBytes.AddRange(loadBytes);//发送报文socket.Send(connBytes.ToArray());// 异步处理开始心跳Task.Run(async () {byte[] pingBytes new byte[2] { 12 4, 0 };//心跳的字节报文是固定的while (true){Console.WriteLine(心跳时间 DateTime.Now.ToString());await Task.Delay(1000);//等待1秒socket.Send(pingBytes);}});//异步处理服务器返回的报文Task.Run(() {//1请求连接 (C-S)//2连接确认 (S-C)//3发布消息 (Both)//4发布收到确认 (QoS 0)//5发布确认收到//6发布释放//7发布完成 (QoS 2)//8订阅请求 (C-S)//9订阅请求确认 (S-C)//10取消订阅请求 (C-S)//11取消订阅请求确认 (S-C)//12心跳请求 (C-S)//13心跳确认 (S-C)//14客户端断开连接 (C-S)byte[] respBytes new byte[1]; //接收MQTT报文类型报文类型占1个字节//连接成功MQTT报文类型CONNACK服务器返回2即0000 0010高低位交换位置就是返回0 0 1 0 0 0 0 0 转成10进制就是32//发布成功MQTT报文类型PUBACK 服务器返回4即0000 0100高低位交换位置就是返回0 1 0 0 0 0 0 0 转成10进制就是64//订阅成功MQTT报文类型SUBACK 服务器返回9即0000 1001高低位交换位置就是返回1 0 0 1 0 0 0 0 转成10进制就是144//心跳成功MQTT报文类型PINGRESP服务器返回13即0000 1101高低位交换位置就是返回1 1 0 1 0 0 0 0 转成10进制就是208while (true)//循环接收{try{socket.Receive(respBytes, 0, 1, SocketFlags.None);int firstValue Convert.ToInt32(respBytes[0]);//Console.WriteLine(第一个字节 firstValue);//根据报文类型进行处理switch (firstValue){case 32:Console.WriteLine(连接成功!);break;case 64:Console.WriteLine(发布成功!);break;case 144:Console.WriteLine(订阅成功!);break;case 208:Console.WriteLine(心跳成功!);break;}}catch (Exception ex){Console.WriteLine(出错了 ex.Message);}}});}/// summary/// 订阅/// /summary/// param nametopics主题列表/paramstatic void Subscription(Liststring topics){Listbyte headerBytes new Listbyte();Listbyte bodyBytes new Listbyte();//第0个字节报文类型10000010byte msgType 8 4; // 1000 0000 headerBytes.Add((byte)(msgType | 2));//第1个字节剩余字节长度等后面计算获取后再添加//第23个字节Package Identifier的长度表示报文的标识int pi random.Next(0, 1000); // Package Identifier的具体值bodyBytes.Add((byte)(pi / 256 % 256));//高位bodyBytes.Add((byte)(pi % 256));//低位//遍历所有主题foreach (var item in topics){//第89个字节topic字符长度byte[] itemBytes Encoding.UTF8.GetBytes(item);bodyBytes.Add((byte)(itemBytes.Length / 256 % 256));bodyBytes.Add((byte)(itemBytes.Length % 256));//第101112131416个字节topic字符内容bodyBytes.AddRange(itemBytes);//第17个字节Qos级别-》 0最多一次的传输1至少一次的传输、至多无限次2有且仅有一次的传输bodyBytes.Add(0x01);}//第1个字节剩余字节长度从第 2 个字节开始。headerBytes.Add((byte)bodyBytes.Count);//组成报文headerBytes.AddRange(bodyBytes);//发送报文socket.Send(headerBytes.ToArray());//接收服务器回应的报文 //byte[] respBytes new byte[5];//socket.Receive(respBytes, 0, 5, SocketFlags.None);//var objSub respBytes; }/// summary/// 发布消息服务级别(Qos1)/// /summarystatic void Publish_Qos1(){#region 方法1Listbyte headerBytes new Listbyte();//报文类型byte msgType 3 4; // 1000 0000 headerBytes.Add((byte)(msgType | 2)); // QoS-0低4位全为1Listbyte bodyBytes new Listbyte();string topic shanghai;string msg hello9098;// 添加主题长度byte[] topicBytes Encoding.UTF8.GetBytes(topic);bodyBytes.Add((byte)(topicBytes.Length / 256 % 256));bodyBytes.Add((byte)(topicBytes.Length % 256));// 添加主题内容bodyBytes.AddRange(topicBytes);// 必须添加Package Identifier只包括它的字节长度int pi random.Next(0, 1000); // Package Identifier//Console.WriteLine(pi);bodyBytes.Add((byte)(pi / 256 % 256));bodyBytes.Add((byte)(pi % 256));// 添加消息长度 byte[] msgBytes Encoding.UTF8.GetBytes(msg);bodyBytes.Add((byte)(msgBytes.Length / 256 % 256));bodyBytes.Add((byte)(msgBytes.Length % 256));// 添加消息内容bodyBytes.AddRange(msgBytes);//添加第1个字节剩余字节长度headerBytes.Add((byte)bodyBytes.Count);// 组装头 headerBytes.AddRange(bodyBytes);//发送消息socket.Send(headerBytes.ToArray());#endregion //#region 方法2//string topic shanghai;//string msg hello9098;//int pi random.Next(0, 1000); // Package Identifier//Listbyte topicbytes new Listbyte();//byte[] topicArray Encoding.UTF8.GetBytes(topic);//byte[] payloadArray Encoding.UTF8.GetBytes(msg);//topicbytes.Add((byte)((int)topicArray.Length / 256));//topicbytes.Add((byte)((int)topicArray.Length % 256));//topicbytes.AddRange(topicArray);//byte[] id new byte[] { (byte)(pi / 256 % 256), (byte)(pi % 256) };//byte[] bufferLen new byte[] { (byte)(topicbytes.Count payloadArray.Length id.Length) };//using (MemoryStream memoryStream new MemoryStream())//{// memoryStream.WriteByte((3 4) | 2 | 1);// 写入消息类型(QoS-1)// memoryStream.Write(bufferLen, 0, (int)bufferLen.Length);// 写入后续报文长度// memoryStream.Write(topicbytes.ToArray(), 0, (int)topicbytes.Count);// 写入Topic字节// memoryStream.Write(id.ToArray(), 0, (int)id.Length);// 写入Package Identifier字节// memoryStream.Write(payloadArray.ToArray(), 0, (int)payloadArray.Length);// 写入消息// byte[] sendArray memoryStream.ToArray();// socket.Send(sendArray);//}接收服务器回应的报文 //byte[] respBytes new byte[4];//socket.Receive(respBytes, 0, 4, SocketFlags.None);//var objSub respBytes;//#endregion }}
}讲解不易分析不易原创不易整理不易伙伴们动动你的金手指你的支持是我最大的动力。
讲解不易分析不易原创不易整理不易伙伴们动动你的金手指你的支持是我最大的动力。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/89841.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!