C#实现TCP通讯协议
本人小白一个,初次使用C#,希望各位大神对小白不足之处能指点一下,O(∩_∩)O谢谢
项目需求:公司锡膏室有四台冰箱,需要对该四台冰箱的温湿度实时采集同时以曲线图方式Show到一块看板上
思路:1,需要将设备发送的数据实时存储至数据库(使用TCP通讯协议实时抓取数据)
2,将数据以曲线图方式Show至看板上(需要使用到AJAX以及强大的JS库【ECharts】})
一,实现数据抓取并存储至数据库:
代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Data.SqlClient; 6 using System.Drawing; 7 using System.IO; 8 9 using System.Net; 10 using System.Net.Sockets; 11 using System.Text; 12 using System.Threading; 13 14 using System.Windows.Forms; 15 16 namespace WindowsFormsApplication1 17 { 18 public partial class Form1 : Form 19 { 20 public Form1() 21 { 22 InitializeComponent(); 23 TextBox.CheckForIllegalCrossThreadCalls = false; 24 } 25 Thread threadWatch = null; // 负责监听客户端连接请求的 线程; 26 Socket socketWatch = null; 27 28 Dictionary<string, Socket> dict = new Dictionary<string, Socket>(); 29 Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>(); 30 31 /// <summary> 32 /// 啟動監控服務 33 /// </summary> 34 /// <param name="sender"></param> 35 /// <param name="e"></param> 36 private void button1_Click(object sender, EventArgs e) 37 { 38 // 创建负责监听的套接字,注意其中的参数; 39 socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 40 // 获得文本框中的IP对象; 41 IPAddress address = IPAddress.Parse(textBox1.Text.Trim()); 42 // 创建包含ip和端口号的网络节点对象; 43 IPEndPoint endPoint = new IPEndPoint(address, int.Parse(textBox2.Text.Trim())); 44 try 45 { 46 // 将负责监听的套接字绑定到唯一的ip和端口上; 47 socketWatch.Bind(endPoint); 48 } 49 catch (SocketException se) 50 { 51 MessageBox.Show("异常:" + se.Message); 52 return; 53 } 54 // 设置监听队列的长度; 55 socketWatch.Listen(10); 56 // 创建负责监听的线程; 57 threadWatch = new Thread(WatchConnecting); 58 threadWatch.IsBackground = true; 59 threadWatch.Start(); 60 ShowMsg("服务器启动监听成功!"); 61 } 62 63 /// <summary> 64 /// 监听客户端请求的方法; 65 /// </summary> 66 void WatchConnecting() 67 { 68 while (true) // 持续不断的监听客户端的连接请求; 69 { 70 // 开始监听客户端连接请求,Accept方法会阻断当前的线程; 71 Socket sokConnection = socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字; 72 // 想列表控件中添加客户端的IP信息; 73 listBox1.Items.Add(sokConnection.RemoteEndPoint.ToString()); 74 // 将与客户端连接的 套接字 对象添加到集合中; 75 dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection); 76 ShowMsg("客户端连接成功!"); 77 Thread thr = new Thread(RecMsg); 78 thr.IsBackground = true; 79 thr.Start(sokConnection); 80 dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr); // 将新建的线程 添加 到线程的集合中去。 81 } 82 } 83 84 85 void RecMsg(object sokConnectionparn) 86 { 87 Socket sokClient = sokConnectionparn as Socket; 88 while (true) 89 { 90 // 定义一个2M的缓存区; 91 byte[] arrMsgRec = new byte[1024 * 1024 * 2]; 92 // 将接受到的数据存入到输入 arrMsgRec中; 93 int length = -1; 94 try 95 { 96 length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度; 97 } 98 catch (SocketException se) 99 { 100 ShowMsg("异常:" + se.Message); 101 // 从 通信套接字 集合中删除被中断连接的通信套接字; 102 dict.Remove(sokClient.RemoteEndPoint.ToString()); 103 // 从通信线程集合中删除被中断连接的通信线程对象; 104 dictThread.Remove(sokClient.RemoteEndPoint.ToString()); 105 // 从列表中移除被中断的连接IP 106 listBox1.Items.Remove(sokClient.RemoteEndPoint.ToString()); 107 break; 108 } 109 catch (Exception e) 110 { 111 ShowMsg("异常:" + e.Message); 112 // 从 通信套接字 集合中删除被中断连接的通信套接字; 113 dict.Remove(sokClient.RemoteEndPoint.ToString()); 114 // 从通信线程集合中删除被中断连接的通信线程对象; 115 dictThread.Remove(sokClient.RemoteEndPoint.ToString()); 116 // 从列表中移除被中断的连接IP 117 listBox1.Items.Remove(sokClient.RemoteEndPoint.ToString()); 118 break; 119 } 120 121 ///--------------------------------------接收客戶端發送過來的信息---------------------------------------------- 122 string strMsg = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length - 1);// 将接受到的字节数据转化成字符串; 123 ShowMsg(strMsg); 124 125 126 ///------------------------------------向客戶端發送回執信息-------------------------------------- 127 string WD = strMsg.Substring(42, 4); 128 string SD = strMsg.Substring(47, 4); 129 string Mdl = strMsg.Substring(21, 10); 130 string ZOOM = strMsg.Substring(32, 1); 131 string SendTime = "20" + strMsg.Substring(3, 17) + ":000"; 132 if (Mdl == "0072916200") { Mdl = "冰箱-01"; } 133 else if (Mdl == "0072915200") { Mdl = "冰箱-03"; } 134 else if (Mdl == "0072914500") { Mdl = "冰箱-04"; } 135 else if (Mdl == "0072912300") { Mdl = "冰箱-02"; } 136 SqlConnection sqlcon = new SqlConnection("Data Source=10.99.106.***;Initial Catalog=PCA_REPORT;User ID=***;pwd=***"); 137 string addx = "INSERT INTO PCA_REPORT..Temperature VALUES ('" + Mdl + "','" + WD + "','" + SD + "','" + SendTime + "',getdate(),'" + ZOOM + "')"; 138 DataSet ds = new DataSet(); 139 SqlDataAdapter adapter = new SqlDataAdapter(addx, sqlcon); 140 adapter.Fill(ds); 141 142 string send = "*RR," + strMsg.Substring(3, 17) + "," + strMsg.Substring(21, 10) + "#"; 143 144 145 146 byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(send); // 将要发送的字符串转换成Utf-8字节数组; 147 byte[] arrSendMsg = new byte[arrMsg.Length + 1]; 148 arrSendMsg[0] = 0; // 表示发送的是消息数据 149 Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length); 150 for (int i = 0; i < listBox1.Items.Count; i++) 151 { 152 string strKey = listBox1.Items[i].ToString(); 153 154 dict[strKey].Send(arrSendMsg);// 解决了 sokConnection是局部变量,不能再本函数中引用的问题; 155 //ShowMsg(send); 156 157 158 } 159 160 } 161 } 162 163 164 165 void ShowMsg(string str) 166 { 167 textBox5.AppendText(str + "\r\n"); 168 } 169 170 private void label2_Click(object sender, EventArgs e) 171 { 172 173 } 174 175 } 176 }
1,将设备与该程式设置为同一网段IP
2,将设备IP指向与当前程式运行的IP(以上程式表明设备指向的IP是:192.168.1.130,指向端口是:9438)
设置以上后,程式就可以接受设备传输的数据了
运行之后如下图:
二,实现将数据以曲线图方式实时Show至看板上
可跳转至:https://download.csdn.net/download/bibabu135766/10274321
看板效果如下图: