一、思路图
![](https://i-blog.csdnimg.cn/blog_migrate/24abf4d8860b622768ee38b144db65a4.png)
二、发数据:客户端 <使用安装的的软件测试> ---服务端 <代码编写> ---串口。(返回数据:串口---服务端---客户端)
![](https://i-blog.csdnimg.cn/blog_migrate/aa6445015bf054406e463c7901fa158f.png)
namespace SerialToNetWork
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//string[] strings = SerialPort.GetPortNames();
}
private void Form1_Load(object sender, EventArgs e)
{
//给数据位下拉框赋值
cbData.Items.AddRange(new object[] {8,7,6,5 });
//获取奇偶校验枚举中的数据名称
string[] paritys = Enum.GetNames(typeof(Parity));
cbParity.Items.AddRange(paritys);
//获取停止位枚举中的数据名称
string[] stops = Enum.GetNames(typeof(StopBits));
cbStop.Items.AddRange(stops);
//初始化ini文件操作
//串口数据
string portName = iniUtil.Read("Serial", "PortName");//名称
int baudRate = iniUtil.ReadInt("Serial", "BaudRate", 4800);//波特率
int dataBits = iniUtil.ReadInt("Serial", "DataBits", 8);//数据位
int parity = iniUtil.ReadInt("Serial", "Parity", 0);//奇偶校验
int stopBits = iniUtil.ReadInt("Serial", "StopBits", 1);//停止位
//网络数据
int port = iniUtil.ReadInt("TcpService", "Port", 8500);//端口
//心跳数据
bool heartbeat = iniUtil.ReadBool("Heartbeat","rbHeart",false);
int heartSpace = iniUtil.ReadInt("Heartbeat","heartSpacer",60*1000);
//需要改ReadStr()
string heartPart = iniUtil.Read("Heartbeat", "heartPart");
bool heartIsHex = iniUtil.ReadBool("Heartbeat", "IsHex", true);
//给文本框赋值
tbSerial.Text = portName;
tbRate.Text = baudRate.ToString();
cbData.Text = dataBits.ToString();
cbParity.SelectedIndex = parity;
cbStop.SelectedIndex = stopBits;
tbPort.Text = port.ToString();
ckIsHex.Checked = heartIsHex;
rbHeartClose.Checked = !heartbeat;
rbHeartOpen.Checked = heartbeat;
tbHeartSpacer.Text = heartSpace.ToString();
tbHeartPart.Text = heartPart;
Task.Run(async () =>
{
while (true)
{
//循环启动串口
StartSerial(portName, baudRate, dataBits, (Parity)parity, (StopBits)stopBits);
await Task.Delay(1000);
}
});
//启动服务端
StartTcpService(port);
//启动心跳
if (heartbeat) //心跳开关
{
byte[] buffer;
if (heartIsHex) //心跳为16进制
{
string[] hexs = heartPart.Split(new string[] { " "},StringSplitOptions.RemoveEmptyEntries);
buffer = new byte[hexs.Length];
for (int i = 0; i < hexs.Length; i++)
{
buffer[i] = Convert.ToByte(hexs[i], 16);
}
}
else //心跳为字符串
{
buffer = Encoding.UTF8.GetBytes(heartPart);
}
timer1.Enabled = true;
timer1.Interval = heartSpace;
timer1.Tick += (s1,e1) =>
{
//发送心跳
if (clients.Count == 0)
{
return;
}
for (int i=0;i<clients.Count;i++)
{
clients[i].Send(buffer);
}
};
}
}
//启动串口
private void StartSerial(string portName, int baudRate, int dataBits, Parity parity, StopBits stopBits)
{
if (serialPort1.IsOpen)
{
return;
}
try
{
serialPort1.PortName = portName;
serialPort1.BaudRate = baudRate;
serialPort1.DataBits = dataBits;
serialPort1.Parity = parity;
serialPort1.StopBits = stopBits;
serialPort1.Open();
Console.WriteLine("串口启动成功");
serialLight.ForeColor = Color.Lime;
}
catch (Exception ex)
{
Console.WriteLine("串口打开失败:"+ex.Message);
serialLight.ForeColor = Color.Black;
}
}
//启动TCP服务端
private List<Socket> clients = new List<Socket>();
Socket service;
private void StartTcpService(int port)
{
service = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
service.Bind(new IPEndPoint(IPAddress.Any, port));
service.Listen(8);
Console.WriteLine("服务端启动成功");
}
catch (Exception ex)
{
Console.WriteLine($"启动服务端异常:+{ex.Message}");
return;
}
Task.Run(() =>
{
while (true)
{
try
{
Socket client = service.Accept();//等待客户端连接
this.BeginInvoke(new Action(() =>
{
TcpServiceLight.ForeColor = Color.Lime;
}));
clients.Add(client);//将客户端连接存入集合
ReceviceClientData(client);//接收客户端消息
} catch (Exception ex)
{
Console.WriteLine("等待客户端连接异常:{0}",ex.Message);
}
}
});
}
//循环接收客户端消息
private void ReceviceClientData(Socket client)
{
Task.Run(() =>
{
try
{
while (true)
{
byte[] buffer = new byte[1024];
int length = client.Receive(buffer);
if (length == 0)
{
throw new Exception("客户端发送的消息长度为0,认为客户端下线了");
}
this.BeginInvoke(new Action(() =>
{
//接收数据时亮灯
LighterUp(ligtherGet);
tbGet.Text = length.ToString() + "字节";
}));
//第3步,把消息发送给串口设备
if (serialPort1.IsOpen)
{
serialPort1.Write(buffer, 0, length);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"接收{client.RemoteEndPoint.ToString()}:客户端消息异常"+ex.Message);
this.BeginInvoke(new Action(() =>
{
tbGet.Text = "0";
}));
CloseTcpClient(client);//关闭客户端
}
});
}
//Tcp服务端接收串口发送过来的消息
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//读取串口数据
byte[] buffer = new byte[serialPort1.BytesToRead];
int length = serialPort1.Read(buffer, 0, buffer.Length);
//给每一个客户端发送数据
int count = clients.Count;
for (int i = 0;i<count;i++)
{
Socket client = clients[i];
//给客户端发送数据
int length1 = client.Send(buffer,0,length,SocketFlags.None);
this.BeginInvoke(new Action(() =>
{
LighterUp(lighterTo);
tbTo.Text = length1.ToString() + "字节";
}));
}
}
//关闭TCP客户端
private void CloseTcpClient(Socket client)
{
if (clients.Contains(client))
{
clients.Remove(client);
}
client?.Close();
this.BeginInvoke(new Action(() =>
{
tbTo.Text = "0";
TcpServiceLight.ForeColor = Color.Black;
}));
}
//接收和发送消息时亮一下灯
private void LighterUp(Control lighter)
{
this.BeginInvoke(new Action(async () =>
{
lighter.BackColor = Color.Lime;
await Task.Delay(60);
lighter.BackColor = Color.White;
}));
}
//清空接收或者发送字节框
private void Clear1_DoubleClick(object sender, EventArgs e)
{
Label lab = sender as Label;
if (lab.Text == "清空接收")
{
tbGet.Text = "0";
}
else if (lab.Text == "清空发送")
{
tbTo.Text = "0";
}
}
//保存数据到ini文件
private void btnSave_Click(object sender, EventArgs e)
{
iniUtil.Write("Serial", "PortName", tbSerial.Text);//串口名称
iniUtil.Write("Serial", "BaudRate", tbRate.Text);//波特率
iniUtil.Write("Serial", "DataBits", cbData.Text);//数据位
iniUtil.Write("Serial", "Parity", cbParity.SelectedIndex.ToString());//奇偶校验
iniUtil.Write("Serial", "StopBits", cbStop.SelectedIndex.ToString());//停止位
iniUtil.Write("TcpService", "Port",tbPort.Text);//端口
iniUtil.Write("Heartbeat", "rbHeart", Convert.ToString(rbHeartOpen.Checked));//心跳是否关闭
iniUtil.Write("Heartbeat", "heartSpacer",tbHeartSpacer.Text);//心跳间隔
iniUtil.Write("Heartbeat", "heartPart", tbHeartPart.Text);//心跳内容
iniUtil.Write("Heartbeat", "IsHex", Convert.ToString(ckIsHex.Checked));//心跳内容
MessageBox.Show("保存成功");
}
//重启
private void startAgain_Click(object sender, EventArgs e)
{
service?.Close();
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
//重启一个程序,方法一
//this.Close();
//Application.ExecutablePath==>获取当前程序路径(包含程序名称exe)
//Process.Start(Application.ExecutablePath);
//方法二
Application.Restart();
}
}
}
三、发生数据:TCP服务端 <安装的测试软件> --- TCP客户端 <代码编写> --- 串口。(返回数据:串口 --- 客户端 --- 服务端)。
![](https://i-blog.csdnimg.cn/blog_migrate/fe5f5ea4d309e41425fa3c914612536b.png)
namespace SerialToNetWorkTcpClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Socket client;
private void btnOpenOrClose_Click(object sender, EventArgs e)
{
if (btnOpenOrClose.Text == "打开客户端")
{
Task.Run(new Action(() =>
{
StartClient();
}));
btnOpenOrClose.Text = "关闭客户端";
btnOpenOrClose.ForeColor = Color.Red;
}
else if(btnOpenOrClose.Text == "关闭客户端")
{
client?.Close();
btnOpenOrClose.Text = "打开客户端";
btnOpenOrClose.ForeColor = Color.Black;
}
}
//开启客户端
private void StartClient()
{
client = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
client.Connect(new IPEndPoint(IPAddress.Parse("192.168.152.1"), 5005));
Console.WriteLine("客户端启动成功");
//循环接收服务端发送过来的数据
while (true)
{
byte[] buffer = new byte[1024];
int length = client.Receive(buffer);
if (length == 0)
{
MessageBox.Show("服务端关闭");
return;
}
//把接收到的服务端数据发给串口
if (serialPort1.IsOpen)
{
serialPort1.Write(buffer, 0, length);
}
}
}
catch(Exception ex)
{
Console.WriteLine("未连接上服务端:"+ex.Message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
Task.Run(new Action(async () =>
{
while (true)
{
StartSearial();
await Task.Delay(1000);
}
}));
}
//启动串口
private void StartSearial()
{
if (!serialPort1.IsOpen)
{
//获取ini文件数据
string portName = iniUtil.Read("Serial", "PortName");//名称
int baudRate = iniUtil.ReadInt("Serial", "BaudRate", 4800);//波特率
int dataBits = iniUtil.ReadInt("Serial", "DataBits", 8);//数据位
int parity = iniUtil.ReadInt("Serial", "Parity", 0);//奇偶校验
int stopBits = iniUtil.ReadInt("Serial", "StopBits", 1);//停止位
//设置串口数据
serialPort1.PortName = portName;
serialPort1.BaudRate = baudRate;
serialPort1.DataBits = dataBits;
serialPort1.Parity = (Parity)parity;
serialPort1.StopBits = (StopBits)stopBits;
try
{
//启动串口
serialPort1.Open();
Console.WriteLine("串口启动成功");
}
catch (Exception ex)
{
Console.WriteLine("串口启动失败:" + ex.Message);
return;
}
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer = new byte[serialPort1.BytesToRead];
int length = serialPort1.Read(buffer,0,buffer.Length);
if (client != null && client.Connected)
{
StringBuilder sb = new StringBuilder();
for (int i =0;i<buffer.Length;i++)
{
sb.Append(buffer[i].ToString("X2")+" ");
}
this.Invoke(new Action(() =>
{
rbData.Text += sb;
}));
client.Send(buffer,0,buffer.Length,SocketFlags.None);
}
}
//清空接收
private void btnClose_Click(object sender, EventArgs e)
{
rbData.Text = "";
}
}
}
四、 发送数据:UDP连接 <安装的测试软件,去连接已经在代码中编写设置好的UDP连接> --- UDP<代码创建一个UDP连接(绑定好IP和端口)> --- 串口。(返回数据:串口 --- 客户端 --- 服务端)。
namespace SerialToNetWorkUdpClient
{
public partial class Form1 : Form
{
//udp服务端接收客户端的指令,发送给串口,在从串口得到的数据转发给客户端
public Form1()
{
InitializeComponent();
}
private void btnOpenOrClose_Click(object sender, EventArgs e)
{
if (btnOpenOrClose.Text == "打开连接")
{
Task.Run(new Action(() =>
{
OpClient();
}));
btnOpenOrClose.Text = "关闭连接";
btnOpenOrClose.ForeColor = Color.Red;
}
else if (btnOpenOrClose.Text == "关闭连接")
{
client?.Close();
btnOpenOrClose.Text = "打开连接";
btnOpenOrClose.ForeColor = Color.Black;
}
}
Socket client = null;
private EndPoint endP;
/// <summary>
/// 开启Udp客户端
/// </summary>
private void OpClient()
{
if (client == null)
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
try
{
client.Bind(new IPEndPoint(IPAddress.Parse("192.168.22.1"), 9000));
Console.WriteLine("Udp客户端连接成功");
endP = new IPEndPoint(0, 0);
//循环接收服务端发送过来的数据
while (true)
{
byte[] buffer = new byte[1024];
int length = client.ReceiveFrom(buffer, ref endP);
if (length == 0)
{
MessageBox.Show("服务端关闭");
return;
}
//把接收到的服务端数据发给串口
if (serialPort1.IsOpen)
{
serialPort1.Write(buffer,0, length);
}
}
}
catch (Exception ex)
{
Console.WriteLine("没有连接:" + ex.Message);
}
}
}
//启动串口
private void StartSearial()
{
if (!serialPort1.IsOpen)
{
//获取ini文件数据
string portName = iniUtil.Read("Serial", "PortName");//名称
int baudRate = iniUtil.ReadInt("Serial", "BaudRate", 4800);//波特率
int dataBits = iniUtil.ReadInt("Serial", "DataBits", 8);//数据位
int parity = iniUtil.ReadInt("Serial", "Parity", 0);//奇偶校验
int stopBits = iniUtil.ReadInt("Serial", "StopBits", 1);//停止位
//设置串口数据
serialPort1.PortName = portName;
serialPort1.BaudRate = baudRate;
serialPort1.DataBits = dataBits;
serialPort1.Parity = (Parity)parity;
serialPort1.StopBits = (StopBits)stopBits;
try
{
//启动串口
serialPort1.Open();
Console.WriteLine("串口启动成功");
}
catch (Exception ex)
{
Console.WriteLine("串口启动失败:" + ex.Message);
return;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
//循环开启串口
Task.Run(new Action(async () =>
{
while (true)
{
StartSearial();
await Task.Delay(1000);
}
}));
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] buffer = new byte[serialPort1.BytesToRead];
int length = serialPort1.Read(buffer, 0, buffer.Length);
if (client != null && !client.Connected)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < buffer.Length; i++)
{
sb.Append(buffer[i].ToString("X2") + " ");
}
this.Invoke(new Action(() =>
{
rbData.Text += sb;
}));
client.SendTo(buffer, 0, buffer.Length, SocketFlags.None,endP);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
rbData.Text = "";
}
}
}