上位机开发
案例1:检测温度、湿度、光感等
本文档使用 MrDoc 发布
-
+
首页
案例1:检测温度、湿度、光感等
# 效果图  # TCP工具类 ```C# using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; namespace 上位机项目.Tools { public class TcpServerTool { #region 事件委托 /// <summary> /// 执行操作消息变更 /// </summary> public event EventHandler<string> ExecuteMessageChanged; /// <summary> /// 客户端个数变更 /// </summary> public event EventHandler<string> ClientCountChanged; #endregion #region 字段、属性 private string _ip = "192.168.137.1"; //ip private int _port = 9000; //端口 private string _ipPort = "192.168.137.1:9000"; // private bool _isConnected = false; //是否连接 private bool _isListened = false; //是否侦听 private NetworkStream _stream; //网络基础流 private Socket _serverSocket; //服务端套接字对象 private Thread listenThread = null; //侦听线程 private List<string> _clientIpPortList = new List<string>(); //客户端Ip端口集合 private List<Socket> _clientSocketList = new List<Socket>(); //客户端套接字对象集合 private List<Thread> _clientSocketThreadList = new List<Thread>(); //接收线程:接收客户端对象集合 public string IP { get => _ip; set => _ip = value; } public int Port { get => _port; set => _port = value; } public bool IsConnected { get => _isConnected; set => _isConnected = value; } public bool IsListened { get => _isListened; set => _isListened = value; } public NetworkStream Stream { get => _stream; set => _stream = value; } public Socket ServerSocket { get => _serverSocket; set => _serverSocket = value; } public List<string> ClientIpPortList { get => _clientIpPortList; set => _clientIpPortList = value; } public List<Socket> ClientSocketList { get => _clientSocketList; set => _clientSocketList = value; } public List<Thread> ClientSocketThreadList { get => _clientSocketThreadList; set => _clientSocketThreadList = value; } public string IpPort { get => _ipPort; set => _ipPort = value; } #endregion #region 构造方法 public TcpServerTool(string ip, int port) { this.IP = ip; this.Port = port; } public TcpServerTool(string ip, string port) { this.IP = ip; if (int.TryParse(port, out int portStr)) { this.Port = portStr; } } #endregion /// <summary> /// 断开连接 /// </summary> public void Disconnect() { //状态 IsListened = false; IsConnected = false; foreach (Thread item in ClientSocketThreadList) { item.Abort(); } //关闭对象集合,清除集合项 foreach (Socket item in ClientSocketList) { item.Close(); } //关闭线程 listenThread?.Abort(); listenThread = null; //关闭流 Stream?.Close(); ServerSocket?.Close(); ServerSocket = null; Stream = null; ClientSocketThreadList?.Clear(); ClientSocketList?.Clear(); ClientIpPortList?.Clear(); } /// <summary> /// 服务端打开 /// </summary> public void Open() { try { IPAddress ipAddress = IPAddress.Parse(IP); //IP地址 // 创建一个新的 Socket 对象,指定为 IPv4、面向流的(TCP)协议 ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //允许套接字复用 ServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // 服务器绑定指定终端(IP,Port) IPEndPoint localEndPoint = new IPEndPoint(ipAddress, Port);//创建终端 ServerSocket.Bind(localEndPoint); //绑定终端 ExecuteMessageChanged?.Invoke(this, $"开始侦听准备..."); ServerSocket.Listen(10); //创建并使用线程侦听 listenThread = new Thread(OnListenClient); listenThread.IsBackground = true; listenThread.Start(); IsListened = true; ExecuteMessageChanged?.Invoke(this, $"本地终端:{ServerSocket.LocalEndPoint}"); ExecuteMessageChanged?.Invoke(this, $"协议:{ServerSocket.LocalEndPoint.AddressFamily}"); ExecuteMessageChanged?.Invoke(this, $"准备完成,开始侦听客户端连接..."); } catch (Exception ex) { ExecuteMessageChanged?.Invoke(this, $"创建连接失败...."); ExecuteMessageChanged?.Invoke(this, $"{ex.Message}"); } } /// <summary> /// 侦听客户端 /// </summary> public void OnListenClient() { try { while (true) { //接受一个客户端的连接请求 Socket socket = ServerSocket.Accept(); ExecuteMessageChanged?.Invoke(this, $"收到来自【{socket.LocalEndPoint}】远程终端的连接请求..."); // 发送消息给客户端 string sendTestData = "Test Connect..."; ExecuteMessageChanged?.Invoke(this, $"尝试发送数据:{sendTestData}"); Send(socket, sendTestData); //创建接收数据线程 Thread thread = new Thread(Received); thread.Name = (ClientSocketThreadList.Count + 1) + ""; thread.IsBackground = true; thread.Start(socket); //添加对象到集合 ClientIpPortList.Add(socket.RemoteEndPoint.ToString()); //添加远程终端到集合 ClientSocketList.Add(socket); //添加Socket对现象到集合 ClientSocketThreadList.Add(thread); //创建对应的客户端Socket线程对象并添加到集合 //触发客户端个数变更事件 ClientCountChanged?.Invoke("Add", socket.RemoteEndPoint.ToString()); } } catch (Exception ex) { ExecuteMessageChanged?.Invoke(this, $"侦听异常:{ex.Message}"); } } /// <summary> /// 接收数据方法 /// </summary> public void Received(object socketClientPara) { Socket socketServer = socketClientPara as Socket; string remoteEndPoint = socketServer.RemoteEndPoint.ToString(); ; while (true) { try { // 读取客户端发送的数据 byte[] buffer = new byte[1024 * 1024]; if (socketServer == null) break; // 接收客户端发来的数据 int dataLength = socketServer.Receive(buffer); // 将接收的数据转换为字符串并输出 string dataReceived = Encoding.ASCII.GetString(buffer, 0, dataLength); ExecuteMessageChanged.Invoke(this, $"{dataReceived}"); } catch (Exception ex) { if (IsListened) { ClientIpPortList.Remove(remoteEndPoint); ClientCountChanged?.Invoke("Remove", remoteEndPoint); Stream = null; ExecuteMessageChanged.Invoke(this, "客户端已断开连接!"); ExecuteMessageChanged.Invoke(this, $"接收异常:{ex.Message}"); ClientSocketList.Find(s => s.RemoteEndPoint.Equals(remoteEndPoint))?.Close(); ClientSocketList.Remove(socketServer); break; } } } } /// <summary> /// 发送数据:根据指定IpPort, /// </summary> public void Send(string ipPort, string data) { try { if (IsListened) { string socketIpPort = ClientIpPortList.Find(s => s.Equals(ipPort)); Socket socket = ClientSocketList.Find(s => s.RemoteEndPoint.ToString().Equals(ipPort)); if (socket != null) { Stream = new NetworkStream(socket); string dataToSend = data; byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend); Stream.Write(dataBytes, 0, dataBytes.Length); ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}"); } else { ExecuteMessageChanged?.Invoke(this, $"发送失败!socket = null"); } } } catch (Exception ex) { ExecuteMessageChanged?.Invoke(this, $"发送异常:{ex.Message}"); } } /// <summary> /// 发送数据:根据指定Socket对象 /// </summary> public void Send(Socket socket, string data) { try { if (IsListened) { if (Stream != null) { string dataToSend = data; byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend); Stream.Write(dataBytes, 0, dataBytes.Length); ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}"); } else { Stream = new NetworkStream(socket); string dataToSend = data; byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend); Stream.Write(dataBytes, 0, dataBytes.Length); ExecuteMessageChanged?.Invoke(this, $"发送数据长度:{dataBytes.Length}"); } } } catch (Exception ex) { ExecuteMessageChanged?.Invoke(this, $"发送异常:{ex.Message}"); } } /// <summary> /// 群发数据:发送数据到所有在连接客户端。 /// </summary> /// <param name="data"></param> public void SendGroup(string data) { try { if (IsListened) { foreach (Socket socket in ClientSocketList) { Stream = new NetworkStream(socket); string dataToSend = data; byte[] dataBytes = Encoding.UTF8.GetBytes(dataToSend); Stream.Write(dataBytes, 0, dataBytes.Length); ExecuteMessageChanged.Invoke(this, $"发送到终端:{socket.RemoteEndPoint}"); ExecuteMessageChanged.Invoke(this, $"协议版本:{socket.RemoteEndPoint.AddressFamily}"); ExecuteMessageChanged.Invoke(this, $"发送数据长度:{dataBytes.Length}"); } } } catch (Exception ex) { ExecuteMessageChanged.Invoke(this, $"发送异常:{ex.Message}"); } } } } ``` # 模型类 ```C# using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using LitJson; namespace 上位机项目.Models { internal class DataM { public double? Temperature { get; set; } public double? Humidity { get; set; } public int? LightPerception { get; set; } public string other { get; set; } public string ToJson() { return JsonMapper.ToJson(this); } public bool SaveJson() { string json = ToJson(); File.WriteAllText("test.json", json); return true; } } } ``` # 源码 ```C# using LitJson; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; using 上位机项目.Models; using 上位机项目.Tools; namespace 上位机项目 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //表格制作初始化 chart1.ChartAreas.Add(new ChartArea()); chart1.Series.Add("温度"); chart1.Series["温度"].ChartType = SeriesChartType.Line; chart1.Series["温度"].IsVisibleInLegend = true; // 显示图例 chart1.Series["温度"].IsValueShownAsLabel = true;//显示数据标签 chart1.Series.Add("湿度"); chart1.Series["湿度"].ChartType = SeriesChartType.Line; chart1.Series["湿度"].IsVisibleInLegend = true; // 显示图例 chart1.Series["湿度"].IsValueShownAsLabel = true;//显示数据标签 chart1.Series.Add("光感"); chart1.Series["光感"].ChartType = SeriesChartType.Line; chart1.Series["光感"].IsVisibleInLegend = true; // 显示图例 chart1.Series["光感"].IsValueShownAsLabel = true;//显示数据标签 chart1.Series.Add("其它"); chart1.Series["其它"].ChartType = SeriesChartType.Line; chart1.Series["其它"].IsVisibleInLegend = true; // 显示图例 chart1.Series["其它"].IsValueShownAsLabel = true;//显示数据标签 listBox1.Items.Add("初始化成功"); } TcpServerTool tst = null; private void button1_Click(object sender, EventArgs e) { tst = new TcpServerTool(textBox1.Text, textBox2.Text); tst.ExecuteMessageChanged += ExcuteMessageChanged; tst.ClientCountChanged += ClientCountChanged; tst.Open(); timer1.Enabled = true; listBox1.Items.Add("开启成功"); } private void ClientCountChanged(object sender, string e) { } private void ExcuteMessageChanged(object sender, string e) { try { DataM dm = JsonMapper.ToObject<DataM>(e); AddDataPoint(dm); Action ac = () => { listBox1.Items.Add($"发送数据成功:{dm.ToJson()}"); listBox1.TopIndex = listBox1.Items.Count - 1; }; listBox1.Invoke(ac); } catch (Exception ex) { Action ac = () => { listBox1.Items.Add($"解析数据错误:{ex.Message}"); listBox1.TopIndex = listBox1.Items.Count - 1; }; listBox1.Invoke(ac); } } private void button2_Click(object sender, EventArgs e) { tst.ExecuteMessageChanged -= ExcuteMessageChanged; tst.ClientCountChanged -= ClientCountChanged; tst?.Disconnect(); tst = null; timer1.Enabled = false; listBox1.Items.Add("断开成功"); listBox1.TopIndex = listBox1.Items.Count - 1; } private void button3_Click(object sender, EventArgs e) { tst.SendGroup(new DataM().ToJson()); listBox1.Items.Add("发送数据"); listBox1.TopIndex = listBox1.Items.Count - 1; } private void button4_Click(object sender, EventArgs e) { } private void AddDataPoint(DataM dm) { Action ac = () => { chart1.Titles.Clear(); int number = chart1.Series["温度"].Points.Count; // 使用当前点的数量作为X值(递增) string x = DateTime.Now.ToString(); double? y = dm.Temperature; // 获取下一个Y值,这里需要你自己的逻辑来生成这个值,温度 double? y1 = dm.Humidity;//湿度 int? y2 = dm.LightPerception;//光感 string y3 = dm.other; chart1.Series["温度"].Points.AddXY(x, y); //添加数据点 chart1.Series["湿度"].Points.AddXY(x, y1); chart1.Series["光感"].Points.AddXY(x, y2); chart1.Series["其它"].Points.AddXY(x, y3); // 设置标题和轴标签 chart1.Titles.Add("环境监测趋势图"); chart1.ChartAreas[0].AxisX.Title = "时间"; chart1.ChartAreas[0].AxisY.Title = "数值"; chart1.ChartAreas[0].AxisY.Interval = 50; // 间隔 if (chart1.Series["温度"].Points.Count > 10) { chart1.Series["温度"].Points.RemoveAt(0); chart1.Series["湿度"].Points.RemoveAt(0); chart1.Series["光感"].Points.RemoveAt(0); chart1.Series["其它"].Points.RemoveAt(0); } }; chart1.Invoke(ac); } private void timer1_Tick(object sender, EventArgs e) { tst.SendGroup(new DataM().ToJson()); } } } ``` # 另一个TCP工具类 ```C# using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; using LitJson; namespace 上位机项目.Tools { public class TcpServerTool { private TcpListener _listener; private bool _isRunning; private readonly List<TcpClient> _clients = new List<TcpClient>(); private readonly int _port; public event Action<string> OnMessageReceived; public event Action<TcpClient> OnClientConnected; public event Action<TcpClient> OnClientDisconnected; public TcpServerTool(int port) { _port = port; } public void Start() { _listener = new TcpListener(IPAddress.Any, _port); _listener.Start(); _isRunning = true; Console.WriteLine($"Server started on port {_port}"); ThreadPool.QueueUserWorkItem(HandleConnections); } private void HandleConnections(object state) { while (_isRunning) { try { TcpClient client = _listener.AcceptTcpClient(); lock (_clients) { _clients.Add(client); } OnClientConnected?.Invoke(client); ThreadPool.QueueUserWorkItem(HandleClientCommunication, client); } catch (SocketException) { /* Server stopped */ } } } private void HandleClientCommunication(object state) { TcpClient client = (TcpClient)state; NetworkStream stream = client.GetStream(); byte[] buffer = new byte[1024]; try { while (_isRunning) { int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; string message = Encoding.UTF8.GetString(buffer, 0, bytesRead); OnMessageReceived?.Invoke(message); } } catch (Exception) { /* Client disconnected */ } finally { lock (_clients) { _clients.Remove(client); } client.Close(); client = null; OnClientDisconnected?.Invoke(client); } } public void SendJson<T>(TcpClient client, T data) { string json = JsonMapper.ToJson(data); byte[] bytes = Encoding.UTF8.GetBytes(json); NetworkStream stream = client.GetStream(); stream.Write(bytes, 0, bytes.Length); } public void BroadcastJson<T>(T data) { lock (_clients) { foreach (var client in _clients) { SendJson(client, data); } } } public void Stop() { _isRunning = false; _listener.Stop(); lock (_clients) { foreach (var client in _clients) { client.Close(); } _clients.Clear(); } Console.WriteLine("Server stopped"); } } } ``` # 工具类用法 ```C# TcpServerTool server = null; private void button1_Click(object sender, EventArgs e) { server = new TcpServerTool(9000); server.OnClientConnected += client => { Console.WriteLine($"Client connected: {client.Client.RemoteEndPoint}"); }; server.OnMessageReceived += message => { try { DataM dm = JsonMapper.ToObject<DataM>(message); AddDataPoint(dm); Action ac = () => { listBox1.Items.Add($"发送数据成功:{dm.ToJson()}"); listBox1.TopIndex = listBox1.Items.Count - 1; }; listBox1.Invoke(ac); } catch (Exception ex) { Action ac = () => { listBox1.Items.Add($"解析数据错误:{ex.Message}"); listBox1.TopIndex = listBox1.Items.Count - 1; }; listBox1.Invoke(ac); } }; server.OnClientDisconnected += client => { if(client != null) { Console.WriteLine($"Client disconnected: {client.Client.RemoteEndPoint}"); } }; server.Start(); timer1.Enabled = true; listBox1.Items.Add("开启成功"); } private void timer1_Tick(object sender, EventArgs e) { server.BroadcastJson(new DataM()); } ```
张泽楠
2025年8月21日 13:57
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码