效果補全(代碼):
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/filestring filePath = Path.Combine(dirPath, "Setting.ini");// debug / file/setting.iniIni = 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 枚舉值。正好對應數據0this.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){//停掉tcpforeach (var item in lists){item.Close(); //關閉所有的客戶端}listen.Stop();panel2.BackColor = Color.Gray;//停掉串口if (serialPort1.IsOpen) serialPort1.Close();//滅燈this.panel1.BackColor = Color.Gray;//開啟tcpstartTCP();//開啟串口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);}}
}