效果补全(代码):
cs
namespace SerialportToTCP
{
public partial class Form1 : Form
{
IniHelper Ini;
string[] botelvs = new string[] { "1200", "4800", "9600", "13200" };
public Form1()
{
InitializeComponent();
//1 读取配置文件
string dirPath = Path.Combine(Application.StartupPath, "File");// debug/file
string filePath = Path.Combine(dirPath, "Setting.ini");// debug / file/setting.ini
Ini = new IniHelper(filePath); //创建读取对象
// 添加串口
comboBox1.Items.AddRange(SerialPort.GetPortNames());// 获取所有串口 拼接在下拉框的items中
comboBox2.Items.AddRange(botelvs);// 添加波特率数组
comboBox2.Items.Add("自定义");//添加一个
comboBox3.Items.AddRange(new string[] { "5", "6", "7", "8" });
comboBox4.Items.AddRange(new string[] { "无", "奇校检", "偶校检" });
comboBox5.Items.AddRange(new string[] { "无", "1", "2", "1.5" });
//2开始处理串口接受数据事件
//处理串口的数据
this.serialPort1.DataReceived += SerialPort1_DataReceived;
//3 处理界面显示默认值 也就是从ini文件读取数据
readSetting();
//4 开始串口通信
startChuanKou();
//5 开始网口通信
startTCP();
}
//开始搭建TCP服务器
TcpListener listen;
List<TcpClient> lists = new List<TcpClient>();//存放所有的客户端
void startTCP()
{
if(!int.TryParse(textBox3.Text,out int port) || port < 1 || port >65563)
{
MessageBox.Show("请输入正确的端口号");
}
//开启服务器 接受客户端
try
{
listen = new TcpListener(System.Net.IPAddress.Any, port);
listen.Start(100); //开始监听
panel2.BackColor = Color.Green;
//把多个客户端接受到数组里面 异步接受
new Task(() => {
try
{
while (true)
{
//接收客户端
TcpClient c1 = listen.AcceptTcpClient();
// 把客户端添加到数组里面 群发需要
lists.Add(c1);
//接收客户端发来的消息
tcpReceive(c1);
}
}
catch
{
MessageBox.Show("TCP服务器关闭");
}
}).Start();
}
catch
{
MessageBox.Show("TCP启动失败");
//把tcp关闭等操作
foreach (var item in lists)
{
item.Close(); //关闭所有的客户端
}
listen.Stop();
panel2.BackColor = Color.Gray;
}
}
//tcp 接收数据
void tcpReceive(TcpClient c1)
{
new Task(() =>
{
NetworkStream stream = c1.GetStream();
try
{
while (c1.Connected) //客户端连接的时候
{
byte[] bs = new byte[1024];
int length = stream.Read(bs, 0, bs.Length);
if (length == 0) throw new Exception(); // 客户端断了
//接收到数据亮灯
tcpLiangDeng();
//把数据转给串口
if (!serialPort1.IsOpen)
{
MessageBox.Show("串口关闭");
break;
}
//把数据转给串口 serialPort1发送数据, com6能接受到消息,
serialPort1.Write(bs, 0, length);
}
}
catch
{
c1.Close();
lists.Remove(c1);
}
}).Start();
}
//tcp 接收到数据亮灯的方法
async void tcpLiangDeng()
{
this.Invoke((Action)(() =>
{
textBox2.Text = (int.Parse(textBox2.Text) + 1).ToString();
//亮灯
panel4.BackColor = Color.Green;
}));
//过一段时间
await Task.Delay(70);
this.Invoke((Action)(() =>
{
//关灯
panel4.BackColor = Color.Gray;
}));
}
void startChuanKou()
{
// 配置串口对象
try
{
this.serialPort1.PortName = comboBox1.Text;//配置串口名称
this.serialPort1.BaudRate = int.Parse(comboBox2.Text); //波特率
this.serialPort1.DataBits = int.Parse( comboBox3.Text);
this.serialPort1.StopBits = (StopBits)comboBox5.SelectedIndex;// 正常赋值 StopBits.None 枚举值。正好对应数据0
this.serialPort1.Parity = (Parity)comboBox4.SelectedIndex; //
this.serialPort1.Open();
//亮灯
this.panel1.BackColor = Color.Green;
}
catch
{
MessageBox.Show("打开串口失败");
//停止串口
if(serialPort1.IsOpen) serialPort1.Close();
//灭灯
this.panel1.BackColor = Color.Gray;
}
}
void readSetting()
{
//先配置串口
comboBox1.SelectedItem = Ini.Read("Serialport", "name", "");
string botelv = Ini.Read("Serialport", "botelv", "9601");
int botelvIndex = Array.IndexOf(botelvs, botelv);// 获取botelv在数组里面的索引值
if (botelvIndex != -1) // 证明波特率在数组里面
{
comboBox2.SelectedIndex= botelvIndex;
comboBox2.DropDownStyle = ComboBoxStyle.DropDownList;
}
else
{
//波特率在数组里面 自定义波特率情况
comboBox2.DropDownStyle = ComboBoxStyle.DropDown; //可编辑的下拉框
//DropDownList 不可编辑的下拉框
comboBox2.Text = botelv;
}
//处理数据位
comboBox3.SelectedItem = Ini.Read("Serialport", "databit", "8");
//处理奇偶校检
comboBox4.SelectedIndex = Ini.Read("Serialport", "parity", 0);
comboBox5.SelectedIndex = Ini.Read("Serialport", "stopbit", 0);
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox3.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox4.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox5.DropDownStyle = ComboBoxStyle.DropDownList;
//网口数据的读取
textBox3.Text = Ini.Read("NetWork", "port", "8080");
if( Ini.Read("NetWork", "heartOn", false))
{
radioButton1.Checked = true;
}
else
{
radioButton2.Checked = true;
}
textBox4.Text= Ini.Read("NetWork", "heartTime", "60000");// 心跳间隔
textBox5.Text = Ini.Read("NetWork", "heartData", ""); //心跳包数据
checkBox1.Checked = Ini.Read("NetWork", "heartHex", false);//s是否采用16进制
}
// 接受串口传递数据
private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] bs = new byte[1024]; //定义一个字节数组
int count = serialPort1.Read(bs, 0, bs.Length); //读取数据到字节数组里面
if (count == 0)
{
//关闭串口
//停止串口
if (serialPort1.IsOpen) serialPort1.Close();
//灭灯
this.panel1.BackColor = Color.Gray;
}
//1 接收到1条串口数据 需要panel3亮一次 封装一个方法控制效果
jieShouDaoChuankou();
//2 转发给所有客户端数据 串口转网口就是把串口数据通过网络转给其他客户端
foreach (var item in lists)
{
item.GetStream().Write(bs, 0, bs.Length);
}
}
async void jieShouDaoChuankou()
{
this.Invoke((Action)(() =>
{
textBox1.Text = (int.Parse(textBox1.Text)+1).ToString();
//亮灯
panel3.BackColor = Color.Green;
}));
//过一段时间
await Task.Delay(70);
this.Invoke((Action)(() =>
{
//关灯
panel3.BackColor = Color.Gray;
}));
}
//波特率下拉框触发变化的时候调用
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox2.SelectedItem.ToString() == "自定义")
{
//切换到自定义选项上
comboBox2.DropDownStyle= ComboBoxStyle.DropDown;
}
else
{
comboBox2.DropDownStyle = ComboBoxStyle.DropDownList;
}
}
//选中心跳开关为开的时候
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
//MessageBox.Show(textBox4.Text + "????/");
if (radioButton1.Checked)
{
//选中心跳
timer1.Interval = string.IsNullOrEmpty(textBox4.Text) ? 2000 : int.Parse(textBox4.Text);
timer1.Tick += Timer1_Tick;
timer1.Start();
}
}
//定时器函数
private void Timer1_Tick(object sender, EventArgs e)
{
//定时发送数据
string data = textBox5.Text; //心跳数据 2选中hex证明把2转成16进制,
byte[] buffer;
if (checkBox1.Checked == true)
{
//需要发16进制的心跳
string[] ds = data.Split(' '); //把2按照空格符号分割成数组结构[2]
buffer = new byte[ds.Length]; //buffer数组长度就是ds的长度
for (int i = 0; i < ds.Length; i++)
{
//System.Globalization.NumberStyles.HexNumber 转成16进制数
//把ds[i]转成16进制
buffer[i] = byte.Parse(ds[i], System.Globalization.NumberStyles.HexNumber);
}
}
else
{
//不采用16进制的心跳包
buffer = Encoding.UTF8.GetBytes(data);
}
foreach (var item in lists)
{
item.GetStream().Write(buffer, 0, buffer.Length);
}
}
//关闭心跳
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
timer1.Stop();
}
//重启
private void button1_Click(object sender, EventArgs e)
{
//停掉tcp
foreach (var item in lists)
{
item.Close(); //关闭所有的客户端
}
listen.Stop();
panel2.BackColor = Color.Gray;
//停掉串口
if (serialPort1.IsOpen) serialPort1.Close();
//灭灯
this.panel1.BackColor = Color.Gray;
//开启tcp
startTCP();
//开启串口
startChuanKou();
}
//保存
private void button2_Click(object sender, EventArgs e)
{
//Serialport", "databit", "8");
Ini.Write("Serialport", "name", comboBox1.Text);
Ini.Write("Serialport", "botelv", comboBox2.Text);
Ini.Write("Serialport", "stopbit", comboBox5.SelectedIndex);
Ini.Write("Serialport", "parity", comboBox4.SelectedIndex);
Ini.Write("Serialport", "databit", comboBox3.Text);//5 6 7 8
Ini.Write("NetWork", "port", textBox3.Text);
Ini.Write("NetWork", "heartOn",radioButton1.Checked);
Ini.Write("NetWork", "heartTime", textBox4.Text);
Ini.Write("NetWork", "heartData", textBox5.Text);
Ini.Write("NetWork", "heartHex", checkBox1.Checked);
}
}
}