Ubuntu C# and windows C# socket TCP communication (with emqx to open the mqtt server)

For the time being, C# is still used on both ends.

  1. TCP client code

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();
        }

    }
}

Remember to unify the IP address (TCP host) and port number before use.

  1. TCP server code

For the time being, please refer to the link above to use 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();
        }
    }
}
  1. mqtt communication preparation work

Code reference link:

Connect to deployment using C# SDK | EMQX Cloud Documentation

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);
        }
    }
}

Please note that the broker's server address is changed to the locally enabled mqtt server, as follows.

3.1 Use emqx to open the mqtt server

Skip quoted paragraphs.

Install dotnet first
dotnet installation_dotlet installation_AI Visual Netqi's Blog-CSDN Blog
My computer is win10 x64, download the LTS version, download link:
Download .NET 6.0 SDK (v6.0.406) - Windows x64 Installer (microsoft.com )
If the installation is successful, enter dotnet --version and its version number will appear. After downloading, I had a preliminary understanding.

Download emqx-5.0.19-windows-amd64.zip. According to the official website, version 5.0 or above is sufficient.

After decompression, open a DOS window in the bin directory of the folder, enter emqx start, and the following screen will appear, indicating that the mqtt server is successfully started.

The mqtt server IP can be queried using ipconfig under the windows system, which is the windows machine ip.

Another: Version problem

20230523 Download emqx-5.0.25-windows-amd64.zip and start it in the above way, it will prompt that there is a problem with the path. As shown below

No solution found, emqx-4.4.18-otp24.3.4.6-windows-amd64 has been used instead.

进入bin目录下运行DOS窗口,输入emqx start,4.x版本运行成功无提示,任务管理器中进程多一项Erlang,如下。即为成功。

3.2安装M2Mqtt.Net

因为参考代码链接中的

using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;

引用到其他命名空间或类,故在VS2019 工具-NuGet包管理器-管理结局方案的NuGet程序包中搜索M2Mqtt,并安装到项目中。

安装成功如图。

  1. 代码集成

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());
        }
    }
}

Guess you like

Origin blog.csdn.net/Suxiang1997/article/details/129476972