赞
踩
上位机开发工作中开始频繁涉及到网口、串口的通讯,网上找了各种资料和帖子都没怎么找到好用的开源代码或者工具。目前找到几个好一点的方式来实现的网口和串口通讯工具包,先写个好用的TCP的negut包记录下来,将使用的步骤写下来做个记录。
本博客主要用来记录自己学到的东西,用于以后回来查看和使用。也会标注来源,各位若是对某项内容感兴趣,可去来源处更加细致的学习
实现效果如下;1、可以监听多个客户端,和限制客户端的连接。2、接收和转发5000行大数据量,快速且无错误。3、可以设置心跳功能,客户端在指定时间内一直不发送数据,会被自动断开。
注:已经看过TCP网口调试助手(一)的朋友 ,可以直接跳到二、3处开始看起
开发工具:Visual Studio 2022
用户界面框架:winform
框架版本:.NET Framework 4.8
选择 “Windows窗体应用(NET Framework)” 项目
输入项目名称:TCP_Server,使用框架为.NET Framework 4.8
右键项目,准备添加TCP的nuget包
使用的nuget包为:STTech.ByteslO.Tcp,版本:2.14.6-alpha0225(也可选择最新版本下载,不必强求版本一致),在nuget管理界面的浏览页面下搜索bytesio,找到nuget包。点击安装并确定
实现代码如下:
- using STTech.BytesIO.Tcp;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace TCP_Server
- {
- public partial class Form1 : Form
- {
- private TcpServer server;
- public Form1()
- {
- InitializeComponent();
-
- //初始化server对象
- server = new TcpServer();
- //设置server的端口号
- server.Port = int.Parse(toolStrip_tbx_port.Text);
-
- //服务启动时触发的事件
- server.Started += Server_Started;
- //服务关闭时触发的事件
- server.Closed += Server_Closed;
- //客户端连接时触发的事件
- server.ClientConnected += Server_ClientConnected;
- //客户端断开连接时触发的事件
- server.ClientDisconnected += Server_ClientDisconnected;
- }
-
- //客户端断开连接时触发的事件,对应的处理函数
- private void Server_ClientDisconnected(object sender, ClientDisconnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]断开连接");
- }
-
- //客户端连接时触发的事件,对应的处理函数
- private void Server_ClientConnected(object sender, ClientConnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]连接成功");
- }
-
- //服务关闭时触发的事件,对应的处理函数
- private void Server_Closed(object sender, EventArgs e)
- {
- Print("停止监听");
- }
-
- //服务启动时触发的事件,对应的处理函数
- private void Server_Started(object sender, EventArgs e)
- {
- Print("开始监听");
- }
- private void Print(string msg)
- {
- //线程的修改直接更新到UI主线程是不被允许的,这里通过调用Form的Invoke方法跨线程访问控件
- this.Invoke(new Action(() =>
- {
- rtbx_log.AppendText($"[{DateTime.Now}] {msg}\r\n");
- }));
-
- }
-
- private void MenuItem_startListen_Click(object sender, EventArgs e)
- {
- //开始监听
- server.StartAsync();
- }
-
-
- private void MenuItem_closeListen_Click(object sender, EventArgs e)
- {
- //停止监听
- server.CloseAsync();
- }
- }
- }
添加修改的部分代码如下:
- //客户端连接时触发的事件,对应的处理函数
- private void Server_ClientConnected(object sender, ClientConnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]连接成功");
- //当客户端有数据返回时触发事件
- e.Client.OnDataReceived += Client_OnDataReceived;
- }
-
- //处理客户端返回过来数据
- private void Client_OnDataReceived(object sender, STTech.BytesIO.Core.DataReceivedEventArgs e)
- {
- TcpClient tcpClient = (TcpClient)sender;
- Print($"来自客户端[{tcpClient.RemoteEndPoint}]的消息:{e.Data.EncodeToString("GBK")}");
- }
这样的效果类似于聊天室,A群友发送的消息,大家伙儿都能看得到
代码量不多,增加代码如下:
- //处理客户端返回过来数据
- private void Client_OnDataReceived(object sender, STTech.BytesIO.Core.DataReceivedEventArgs e)
- {
- TcpClient tcpClient = (TcpClient)sender;
- Print($"来自客户端[{tcpClient.RemoteEndPoint}]的消息:{e.Data.EncodeToString("GBK")}");
-
- //收到某个客户端数据后,遍历server中客户端
- foreach(TcpClient client in server.Clients)
- {
- //找到非当前发数据的客户端
- if (client != tcpClient)
- {
- //给这个客户端转发消息
- client.SendAsync(e.Data);
- }
- }
- }
可以设置服务端的容量上限,也可以限制某个区段的ip地址不可以连接我们的服务端。代码如下:
- public Form1()
- {
- InitializeComponent();
-
- //初始化server对象
- server = new TcpServer();
- //设置server的端口号
- server.Port = int.Parse(toolStrip_tbx_port.Text);
-
- //服务启动时触发的事件
- server.Started += Server_Started;
- //服务关闭时触发的事件
- server.Closed += Server_Closed;
- //客户端连接时触发的事件
- server.ClientConnected += Server_ClientConnected;
- //客户端断开连接时触发的事件
- server.ClientDisconnected += Server_ClientDisconnected;
-
- //接收客户端连接时的处理过程,加个服务端上限为只能容纳三个客户端
- server.ClientConnectionAcceptedHandle = (s, e) =>
- {
- if (server.Clients.Count() < 3)
- {
- return true;
- }
- else
- {
- Print($"服务器已满,关闭客户端[{e.ClientSocket.RemoteEndPoint}]的连接");
- return false;
- }
- };
- }
如果某个客户端在一定时间内没有给服务端发送数据,就会自动断开。使用代码如下:
- //客户端连接时触发的事件,对应的处理函数
- private void Server_ClientConnected(object sender, ClientConnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]连接成功");
- //当客户端有数据返回时触发事件
- e.Client.OnDataReceived += Client_OnDataReceived;
- //和客户端建立心跳,如果客户端多长时间没回消息,就断开连接,3000单位是ms
- e.Client.UseHeartbeatTimeout(3000);
- }
- using STTech.BytesIO.Core;
- using STTech.BytesIO.Tcp;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- namespace TCP_Server
- {
- public partial class Form1 : Form
- {
- private TcpServer server;
- public Form1()
- {
- InitializeComponent();
-
- //初始化server对象
- server = new TcpServer();
- //设置server的端口号
- server.Port = int.Parse(toolStrip_tbx_port.Text);
-
- //服务启动时触发的事件
- server.Started += Server_Started;
- //服务关闭时触发的事件
- server.Closed += Server_Closed;
- //客户端连接时触发的事件
- server.ClientConnected += Server_ClientConnected;
- //客户端断开连接时触发的事件
- server.ClientDisconnected += Server_ClientDisconnected;
-
- //接收客户端连接时的处理过程,加个服务端上限为只能容纳三个客户端
- server.ClientConnectionAcceptedHandle = (s, e) =>
- {
- if (server.Clients.Count() < 3)
- {
- return true;
- }
- else
- {
- Print($"服务器已满,关闭客户端[{e.ClientSocket.RemoteEndPoint}]的连接");
- return false;
- }
- };
- }
-
- //客户端断开连接时触发的事件,对应的处理函数
- private void Server_ClientDisconnected(object sender, ClientDisconnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]断开连接");
- }
-
- //客户端连接时触发的事件,对应的处理函数
- private void Server_ClientConnected(object sender, ClientConnectedEventArgs e)
- {
- Print($"客户端[{e.Client.Host}:{e.Client.Port}]连接成功");
- //当客户端有数据返回时触发事件
- e.Client.OnDataReceived += Client_OnDataReceived;
- //和客户端建立心跳,如果客户端多长时间没回消息,就断开连接,3000单位是ms
- e.Client.UseHeartbeatTimeout(3000);
- }
-
- //处理客户端返回过来数据
- private void Client_OnDataReceived(object sender, STTech.BytesIO.Core.DataReceivedEventArgs e)
- {
- TcpClient tcpClient = (TcpClient)sender;
- Print($"来自客户端[{tcpClient.RemoteEndPoint}]的消息:{e.Data.EncodeToString("GBK")}");
-
- //收到某个客户端数据后,遍历server中客户端
- foreach(TcpClient client in server.Clients)
- {
- //找到非当前发数据的客户端
- if (client != tcpClient)
- {
- //给这个客户端转发消息
- client.SendAsync(e.Data);
- }
- }
- }
-
- //服务关闭时触发的事件,对应的处理函数
- private void Server_Closed(object sender, EventArgs e)
- {
- Print("停止监听");
- }
-
- //服务启动时触发的事件,对应的处理函数
- private void Server_Started(object sender, EventArgs e)
- {
- Print("开始监听");
- }
- private void Print(string msg)
- {
- //线程的修改直接更新到UI主线程是不被允许的,这里通过调用Form的Invoke方法跨线程访问控件
- this.Invoke(new Action(() =>
- {
- rtbx_log.AppendText($"[{DateTime.Now}] {msg}\r\n");
- }));
-
- }
-
- private void MenuItem_startListen_Click(object sender, EventArgs e)
- {
- //开始监听
- server.StartAsync();
- }
-
-
- private void MenuItem_closeListen_Click(object sender, EventArgs e)
- {
- //停止监听
- server.CloseAsync();
- }
- }
- }
主要使用了服务端和客户端的连接、接收数据、群转发接收到的数据、对客户端的限制连接和心跳功能。传输速度不错,大数据量传输未出错。
原内容出处:C# TCP服务端_哔哩哔哩_bilibili
注:单身狗注意,原视频狗粮很多!!!
源代码(本文中自己试验写的程序):TCP_Server · jifengtu/ShareSpace - 码云 - 开源中国 (gitee.com)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。