ubuntu C# 和windows C# socket TCP通信(附用emqx开启mqtt服务器)

暂时两端都还是用C#。

  1. 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主机)和端口号。

  1. 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();
        }
    }
}
  1. 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,并安装到项目中。

安装成功如图。

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

猜你喜欢

转载自blog.csdn.net/Suxiang1997/article/details/129476972
今日推荐