阅读量:1
文章所用工具
http://t.csdnimg.cn/2gIR8http://t.csdnimg.cn/2gIR8
搭建服务器界面
操作配置文件保存方式类
public string FileName { get; set; } public IniHelper(string name) { this.FileName = name; //在构造函数中给路径赋值 }
1 先导入c语言进行读取操作ini文件的方法
GetPrivateProfileString() 获取ini配置文件的数据
//static 静态的变量 只能声明在当前文件中,不能在其他源文件进行使用。
//extern 用来声明外部的符号 可以跨文件使用。
[DllImport("Kernel32.dll")] //导入方法所在dll文件 public static extern Int32 GetPrivateProfileString( string sectionName, //段名 string keyName,//键名 string defaultName,//当键不存在默认值。 StringBuilder returnValue,// 读取到数据 uint size,// 读取数据的大小 string fileName// ini文件路径 );
2添加写入ini文件的c方法
[DllImport("Kernel32.dll")] public static extern Int32 WritePrivateProfileString( string sectionName, //段名 string keyName,//键名 string value,//设置的值 string fileName// ini文件路径 );
不直接使用上面的俩个c语言的方法 再封装到其他方法进行使用
//读取ini数据的方法
//ReadData("Second","B","Setting.ini") "10"
//参数1 段名 ,参数2键名 ,参数3是文件路径
public static string ReadData(string sectionName,string keyName,string fileName) { StringBuilder sb = new StringBuilder(512); //512是存储的大小 GetPrivateProfileString(sectionName, keyName, string.Empty, sb, 512, fileName); return sb.ToString(); }
对上面ReadData再封装,封装能直接返回指定类型的数据的方法
//传进段名和键名获取内容
//以后Read("段名","键名") 返回字符串类型
public string Read(string sectionName,string keyName) { return ReadData(sectionName, keyName,this.FileName); }
如果读取数据 没读取到 给赋一个初值
Read("Secotion",A,"1000") 最终结果:hello world
Read("Secotion",C,"1000") 最终结果:1000
public string Read(string sectionName, string keyName,string defaultValue) { string v = Read(sectionName, keyName); if (string.IsNullOrEmpty(v)) { return defaultValue; } return v; }
读取的时候 返回一个整型的数据值
Read("Secotion",C,1000) 最终结果:1000
Read("Secotion",A,1000) 最终结果:1000
public int Read(string s1, string k1, int d1) { string v = Read(s1, k1); if (int.TryParse(v,out int value)) { return value; } else { return d1; } }
public bool Read(string s1, string k1, bool d1) { string v = Read(s1, k1); if (bool.TryParse(v,out bool value)) { return value; } else { //不能转成bool if (v=="1"||v=="OK"||v=="ON"||v=="YES") { return true; } else if(v=="0"||v=="NO"||v=="OFF"||v.ToUpper()=="OFF") { //如果值以上几种请求 值为false return false; } else { return d1; } } } //ini值是double类型 public double Read(string s1, string k1, double d1) { string v = Read(s1, k1); if (double.TryParse(v, out double value)) { return value; } else { return d1; } }
封装写入数据的方法
先定义一个静态写入方法
public static int WriteData(string s1,string k1,string v,string file) { return WritePrivateProfileString(s1,k1,v,file); }
封装方法
//在封装Write方法传递 传进段名 键名 值是字符串 public int Write(string s1,string k1,string v1) { return WriteData(s1, k1, v1, this.FileName); } //在封装Write方法传递 传进段名 键名 值是整型 public int Write(string s1, string k1, int v1) { return WriteData(s1, k1, v1.ToString(), this.FileName); } //在封装Write方法传递 传进段名 键名 值是bool public int Write(string s1, string k1, bool v1) { return WriteData(s1, k1, v1?"1":"0", this.FileName); } //在封装Write方法传递 传进段名 键名 值是时间格式 public int Write(string s1, string k1, DateTime v1) { return WriteData(s1, k1, v1.ToString("yyyy-MM-dd HH-mm:ss"), this.FileName); }
using调用
编辑配置文件
存入File文件夹中,放到Dubug文件夹中
服务器
IniHelper Ini; string[] botelvs = new string[] { "1200", "4800", "9600", "13200" };
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_DataReceivd; // 3 处理界面显示默认值 也就是从ini文件读取数据 readStting(); // 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 (Exception ex) { MessageBox.Show("TCP启动失败"); // 把tcp关闭等操作 foreach(var item in lists) { item.Close(); // 关闭所有的客户端 } listen.Stop(); panel2.BackColor = Color.Gray; } }
接收数据
void tcpReceive(TcpClient c1) { new Task(() => { NetworkStream stream = c1.GetStream(); try { MessageBox.Show("111"); 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; } // 把数据转给串口 发送数据,com8能接收到消息, serialPort1.Write(bs, 0, length); } } catch { c1.Close(); lists.Remove(c1); } }).Start(); }
亮灯
async void tcpLiangDeng() { this.Invoke((Action)(() => { textBox2.Text = (int.Parse(textBox2.Text) + 1).ToString(); // 亮灯 panel4.BackColor = Color.Pink; })); // 过一段时间 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 枚举值 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; } } private void readStting() { // 先配置串口 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; } 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 { radioButton1.Checked = true; } textBox4.Text = Ini.Read("NetWork", "heartTime", "60000"); // 心跳间隔 textBox5.Text = Ini.Read("NetWork", "heartTime", ""); // 心跳间隔 checkBox1.Checked = Ini.Read("NetWork", "heartTime", false); // 心跳间隔 }
接收串口传递的数据
private void SerialPort1_DataReceivd(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 接收到一条窗口数据 需要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.Pink; })); // 过一段时间 await Task.Delay(70); this.Invoke((Action)(() => { textBox1.Text = (int.Parse(textBox1.Text) + 1).ToString(); // 关灯 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) { if(radioButton1.Checked) { // 选中心跳 timer1.Interval = string.IsNullOrEmpty(textBox4.Text) ? 6000 : int.Parse(textBox4.Text); timer1.Tick += Timer1_Tick; timer1.Start(); } }
定时发送数据
private void Timer1_Tick(object sender, EventArgs e) { // 定时发送数据 string data = textBox5.Text; // 心跳数据 选中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); } }
关闭心跳
rivate 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); }
接受和发送默认值
效果如下
QQ202473-20354