暂时两端都还是用C#。
TCP客户端代码
windows C#
https://www.cnblogs.com/sunev/archive/2012/08/05/2604189.html
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
namespace client
{
class Program
{
static void Main(string[] args)
{
//定义发送数据缓存
byte[] data = new byte[1024];
//定义字符串,用于控制台输出或输入
string input, stringData;
//定义主机的IP及端口
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEnd = new IPEndPoint(ip, 5566);
//定义套接字类型
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//尝试连接
try
{
socket.Connect(ipEnd);
}
//异常处理
catch (SocketException e)
{
Console.Write("Fail to connect server");
Console.Write(e.ToString());
return;
}
//定义接收数据的长度
int recv = socket.Receive(data);
//将接收的数据转换成字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出接收到的数据
Console.Write(stringData);
//定义从键盘接收到的字符串
input = Console.ReadLine();
//将从键盘获取的字符串转换成整型数据并存储在数组中
data = Encoding.ASCII.GetBytes(input);
//发送该数组
socket.Send(data, data.Length, SocketFlags.None);
while (true)
{
//
//如果字符串是"exit",退出while循环
if (input == "exit")
{
break;
}
//对data清零
data = new byte[1024];
//定义接收到的数据的长度
recv = socket.Receive(data);
//将接收到的数据转换为字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出字符串
Console.Write(stringData);
//发送收到的数据
socket.Send(data, recv, 0);
}
Console.Write("disconnect from server");
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
}
}
使用前记得统一IP地址(TCP主机)和端口号。
TCP服务端代码
暂时也参考上面链接用C#。
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
namespace net
{
class Program
{
static void Main(string[] args)
{
//定义接收数据长度变量
int recv;
//定义接收数据的缓存
byte[] data = new byte[1024];
//定义侦听端口
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 5166);
//定义套接字类型
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//连接
socket.Bind(ipEnd);
//开始侦听
socket.Listen(10);
//控制台输出侦听状态
Console.Write("Waiting for a client");
//一旦接受连接,创建一个客户端
Socket client = socket.Accept();
//获取客户端的IP和端口
IPEndPoint ipEndClient = (IPEndPoint)client.RemoteEndPoint;
//输出客户端的IP和端口
Console.Write("Connect with {0} at port {1}", ipEndClient.Address, ipEndClient.Port);
//定义待发送字符
string welcome = "Welcome to my server";
//数据类型转换
data = Encoding.ASCII.GetBytes(welcome);
//发送
client.Send(data, data.Length, SocketFlags.None);
while (true)
{
//对data清零
data = new byte[1024];
//获取收到的数据的长度
recv = client.Receive(data);
//如果收到的数据长度为0,则退出
if (recv == 0)
break;
//输出接收到的数据
Console.Write(Encoding.ASCII.GetString(data, 0, recv));
//将接收到的数据再发送出去
client.Send(data, recv, SocketFlags.None);
}
Console.Write("Disconnect form{0}", ipEndClient.Address);
client.Close();
socket.Close();
}
}
}
mqtt通信准备工作
代码参考链接:
使用 C# SDK 连接到部署 | EMQX Cloud 文档
using System;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace csharpMQTT
{
class Program
{
static MqttClient ConnectMQTT(string broker, int port, string clientId, string username, string password)
{
MqttClient client = new MqttClient(broker, port, false, MqttSslProtocols.None, null, null);
client.Connect(clientId, username, password);
if (client.IsConnected)
{
Console.WriteLine("Connected to MQTT Broker");
}
else
{
Console.WriteLine("Failed to connect");
}
return client;
}
static void Publish(MqttClient client, string topic)
{
int msg_count = 0;
while (true)
{
System.Threading.Thread.Sleep(1 * 1000);
string msg = "messages: " + msg_count.ToString();
client.Publish(topic, System.Text.Encoding.UTF8.GetBytes(msg));
Console.WriteLine("Send `{0}` to topic `{1}`", msg, topic);
msg_count++;
}
}
static void Subscribe(MqttClient client, string topic)
{
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE });
}
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
string payload = System.Text.Encoding.Default.GetString(e.Message);
Console.WriteLine("Received `{0}` from `{1}` topic", payload, e.Topic.ToString());
}
static void Main(string[] args)
{
string broker = "broker.emqx.io";//服务器地址,默认为云端服务器
//string broker = "115.156.168.35"; //本地服务器ip
int port = 1883;
string topic = "Csharp/mqtt";
string clientId = Guid.NewGuid().ToString();
string username = "emqx";
string password = "public";
MqttClient client = ConnectMQTT(broker, port, clientId, username, password);
Subscribe(client, topic);
Publish(client, topic);
}
}
}
需注意broker的服务器地址修改为本地开启的mqtt服务器,如下。
3.1用emqx开启mqtt服务器
跳过引用段。
先安装dotnet
dotnet安装_dotlet安装_AI视觉网奇的博客-CSDN博客
我的电脑是win10 x64,下载LTS版本,下载链接:
下载 .NET 6.0 SDK (v6.0.406) - Windows x64 Installer (microsoft.com)
如安装成功,输入dotnet --version将出现其版本号。下载后进行了初步了解。
下载emqx-5.0.19-windows-amd64.zip,根据官网提示,5.0版本以上即可。
解压后在文件夹bin目录下打开DOS窗口,输入emqx start,出现如下画面,即开启mqtt服务器成功。
mqtt服务器IP可以在windows系统下用ipconfig查询,即windows机ip。
另:版本问题
20230523下载emqx-5.0.25-windows-amd64.zip按照上述方式启动会提示路径有问题。如下图
没有找到解决方法,已改用emqx-4.4.18-otp24.3.4.6-windows-amd64。
进入bin目录下运行DOS窗口,输入emqx start,4.x版本运行成功无提示,任务管理器中进程多一项Erlang,如下。即为成功。
3.2安装M2Mqtt.Net
因为参考代码链接中的
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
引用到其他命名空间或类,故在VS2019 工具-NuGet包管理器-管理结局方案的NuGet程序包中搜索M2Mqtt,并安装到项目中。
安装成功如图。
代码集成
windows 端C#代码兼具上文中的TCP Client和 mqtt 客户端功能。代码如下:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
namespace client
{
class Program
{
//是否启动mqtt作为中转的标志位
static bool isTransfer = true;
//全局,接收mqtt发布的信息msg
static string msg_mqtt_publish = "Waiting for MQTT publish...";
static byte[] _data;
static int _recv;
static Socket _socket;
static string _stringData;
static void Main(string[] args)
{
if (isTransfer)
{
//mqtt-第1段
//服务器地址,默认为云端服务器
//string broker = "broker.emqx.io";
string broker = "115.156.168.35"; //本地服务器ip
int port = 1883;
string topic = "Csharp/mqtt";
string clientId = Guid.NewGuid().ToString();
// string username = "emqx";
// string password = "public";
//本地服务器用户名密码可以为空
string username = "";
string password = "";
MqttClient client = ConnectMQTT(broker, port, clientId, username, password);
Subscribe(client, topic);
//TCP-第1段
//定义发送数据缓存
byte[] data = new byte[1024];
//定义字符串,用于控制台输出或输入
string stringData;
//定义主机的IP及端口
IPAddress ip = IPAddress.Parse("10.11.47.31");
IPEndPoint ipEnd = new IPEndPoint(ip, 5166);
//定义套接字类型
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//尝试连接
try
{
socket.Connect(ipEnd);
}
//异常处理
catch (SocketException e)
{
Console.Write("Fail to connect TCP server");
Console.Write(e.ToString());
return;
}
//定义接收数据的长度
int recv = socket.Receive(data);
//将接收的数据转换成字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出接收到的数据
//Console.WriteLine("Received from Server: " + stringData);
Console.WriteLine("Received from TCP Server: " + msg_mqtt_publish + "——Main()");
//如果启动中转,则将mqtt中Publish的输出结果赋给data
data = Encoding.ASCII.GetBytes(msg_mqtt_publish);
//发送该数组
socket.Send(data, data.Length, SocketFlags.None);
//全局变量数据传输的内容给Publish()里面的DataSet()用
_data = data;
_recv = recv;
_socket = socket;
_stringData = stringData;
//mqtt和TCP-第2段
Publish(client, topic);//Publish()里面有while(true),不会退出循环,将原TCP中的while(true)内容移植
}
else
SocketTCP();
}
//SocketTCP通信集成方法
static void SocketTCP()
{
//定义发送数据缓存
byte[] data = new byte[1024];
//定义字符串,用于控制台输出或输入
string input, stringData;
//定义主机的IP及端口
IPAddress ip = IPAddress.Parse("10.11.47.31");
IPEndPoint ipEnd = new IPEndPoint(ip, 5166);
//定义套接字类型
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//尝试连接
try
{
socket.Connect(ipEnd);
}
//异常处理
catch (SocketException e)
{
Console.Write("Fail to connect server");
Console.Write(e.ToString());
return;
}
//定义接收数据的长度
int recv = socket.Receive(data);
//将接收的数据转换成字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出接收到的数据
Console.WriteLine("Received from Server: " + stringData);
//if (isTransfer)
//{
// //如果启动中转,则将mqtt中Publish的输出结果赋给data
// data = Encoding.ASCII.GetBytes(msg_mqtt_publish);
// input = null;
//}
//else
//{
//定义从键盘接收到的字符串
input = Console.ReadLine();
//将从键盘获取的字符串转换成整型数据并存储在数组中
data = Encoding.ASCII.GetBytes(input);
//}
//发送该数组
socket.Send(data, data.Length, SocketFlags.None);
//if (isTransfer)
// DataReset(data, recv, socket, stringData);
//else
{
while (true)
{
//如果字符串是"exit",退出while循环
if (input == "exit")
{
break;
}
//对data清零
data = new byte[1024];
//定义接收到的数据的长度
recv = socket.Receive(data);
//将接收到的数据转换为字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//控制台输出字符串
Console.Write(stringData);
//发送收到的数据
socket.Send(data, recv, 0);
}
}
Console.WriteLine("disconnect from server");
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
/// <summary>
/// 发送接收到的字符串,仅供中转时使用
/// </summary>
/// <param name="data"></param>
/// <param name="recv"></param>
/// <param name="socket"></param>
/// <param name="stringData"></param>
static void DataReset(byte[] data, int recv, Socket socket, string stringData)
{
//这里不能再是收到的数据了,要更新为msg_mqtt_publish
//对data清零
data = new byte[1024];
//定义接收到的数据的长度
recv = socket.Receive(data);
//将接收到的数据转换为字符串
stringData = Encoding.ASCII.GetString(data, 0, recv);
//将从msg_mqtt_publish获取的字符串转换成整型数据并存储在数组中
data = Encoding.ASCII.GetBytes(msg_mqtt_publish);
//控制台输出接收到的字符串
Console.WriteLine("Received from TCP Server: " + stringData + "——DataReset()");
//把新的msg_mqtt_publish发出去
recv = data.Length;
//发送新的msg_mqtt_publish数据
socket.Send(data, recv, 0);
}
//以下为mqtt相关方法
static MqttClient ConnectMQTT(string broker, int port, string clientId, string username, string password)
{
MqttClient client = new MqttClient(broker, port, false, MqttSslProtocols.None, null, null);
client.Connect(clientId, username, password);
if (client.IsConnected)
{
Console.WriteLine("Connected to MQTT Broker");
}
else
{
Console.WriteLine("Failed to connect to MQTT");
}
return client;
}
static void Publish(MqttClient client, string topic)
{
int msg_count = 0;
while (true)
{
System.Threading.Thread.Sleep(1 * 1000);
string msg = "messages: " + msg_count.ToString();
msg_mqtt_publish = msg;//实时更新msg_mqtt_publish
client.Publish(topic, System.Text.Encoding.UTF8.GetBytes(msg_mqtt_publish));
Console.WriteLine("Send `{0}` to topic `{1}`", msg_mqtt_publish, topic);
msg_count++;
DataReset(_data, _recv, _socket, _stringData);
}
}
static void Subscribe(MqttClient client, string topic)
{
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE });
}
static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
string payload = System.Text.Encoding.Default.GetString(e.Message);
Console.WriteLine("Received `{0}` from `{1}` topic", payload, e.Topic.ToString());
}
}
}