[C#] 建立UDP連接、發送廣播

說明:

  通過建立本地UdpClient與遠程UdpClient進行通訊,亦可直接發送到其他已存在的遠程端。

  基本原理:構建一個本地的udpcSend實例,開啓多線程進行監聽,然後再發送廣播。

  案例有字節數組與十六進制字符串相互轉換的方法。

 

一、案例源碼

  窗體的主要代碼:FrmMain.cs

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Net;
  8 using System.Net.Sockets;
  9 using System.Text;
 10 using System.Threading;
 11 using System.Threading.Tasks;
 12 using System.Windows.Forms;
 13 
 14 namespace NetworkService
 15 {
 16     public partial class FrmMain : Form
 17     {
 18         public FrmMain()
 19         {
 20             InitializeComponent();
 21 
 22             //string msg = "FF FB 0F";
 23             //byte[] bytes = Encoding.Default.GetBytes(msg);
 24             
 25 
 26             //string res = "";
 27             //for (int i = 0; i < bytes.Length; i++)
 28             //{
 29             //    res += bytes[i].ToString();
 30             //}
 31             //MessageBox.Show(res);
 32 
 33 
 34         }
 35 
 36         //本地收發UDPClient實例
 37         private UdpClient udpcSend;
 38         private UdpClient udpcRecv;
 39         private bool isLocalConneted = false;//本地是否已連接
 40         private Thread thrRecv;//本地監聽接收線程
 41 
 42         /// <summary>
 43         /// 【構建本地連接】
 44         ///  20181021
 45         /// </summary>
 46         /// <param name="sender"></param>
 47         /// <param name="e"></param>
 48         private void btnConnect_Click(object sender, EventArgs e)
 49         {
 50             if (cbProtocol.SelectedIndex != 0)
 51             {
 52                 MessageBox.Show("請暫時選擇UDP協議!", "系統提示");
 53                 return;
 54             }
 55 
 56             if (string.IsNullOrWhiteSpace(tbLocalIP.Text) || string.IsNullOrWhiteSpace(tbLocalPort.Text))
 57             {
 58                 MessageBox.Show("請填寫本地IP和端口", "系統提示");
 59                 return;
 60             }
 61 
 62 
 63             if (!isLocalConneted)//構建本地連接
 64             {
 65                 IPEndPoint localIpep = new IPEndPoint(IPAddress.Parse(tbLocalIP.Text), Convert.ToInt32(tbLocalPort.Text));
 66                 udpcSend = new UdpClient(localIpep);
 67 
 68                 btnConnect.Text = "斷開";
 69                 isLocalConneted = true;
 70 
 71                 //啓動監聽接收信息
 72                 BeginListenRecv();
 73             }
 74             else//斷開本地連接
 75             {
 76                 //關閉監聽線程
 77                 thrRecv.Abort();
 78                 udpcRecv.Close();
 79 
 80                 udpcSend.Close();
 81                 btnConnect.Text = "連接";
 82                 isLocalConneted = false;
 83 
 84 
 85                 ShowMessage(tbRecvMsg, "[OS]:UDP監聽已成功關閉");
 86             }
 87         }
 88 
 89         
 90         
 91         /// <summary>
 92         /// 【開始監聽】
 93         ///  20181021
 94         /// </summary>
 95         private void BeginListenRecv()
 96         {
 97             udpcRecv = udpcSend;//接收與發送使用同一個實例
 98 
 99             thrRecv = new Thread(ReceiveMessage);
100             thrRecv.Start();
101 
102             ShowMessage(tbRecvMsg, "[OS]:Local UDP 監聽已成功啓動");
103 
104         }
105 
106         /// <summary>
107         /// 【接收信息】
108         ///  20181021
109         /// </summary>
110         private void ReceiveMessage()
111         {
112             IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);//接收任何來源的信息
113             while (true)
114             {
115                 byte[] byteRecv = udpcRecv.Receive(ref remoteIpep);
116                 string message = ByteArrayToHexStringNoBlank(byteRecv);
117 
118                 //remoteIpep.Address.ToString() 獲取發送源的IP
119                 ShowMessage(tbRecvMsg, "[Local Recv]:" + remoteIpep.Address + ":" + remoteIpep.Port + "=" + message);
120 
121             }
122 
123         }
124 
125         /// <summary>
126         /// 【發送消息】
127         ///  20181021
128         /// </summary>
129         /// <param name="obj"></param>
130         private void SendMessage(object obj)
131         {
132             string[] data = (string[])obj;
133 
134             //字符串轉16進制
135             byte[] sendBytes = HexStringToByteArray(data[0]);
136 
137             //發送到遠程IP和端口
138             IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse(data[1]), Convert.ToInt32(data[2]));
139 
140             udpcSend.Send(sendBytes, sendBytes.Length, remoteIpep);
141 
142             
143             ShowMessage(tbRecvMsg, "[Local Send]:" + data[0]);
144             ResetTextBox(tbSendMsg);
145         }
146 
147 
148         //構建遠程服務的收發實例
149         private UdpClient remoteUdpcSend;
150         private UdpClient remoteUdpcRecv;
151         private Thread remoteThrRecv;
152 
153         private Thread thrSend;
154         private bool isRemoteCreated = false;
155         /// <summary>
156         /// 【發送消息】
157         ///  20181021
158         /// </summary>
159         /// <param name="sender"></param>
160         /// <param name="e"></param>
161         private void btnSend_Click(object sender, EventArgs e)
162         {
163             if (string.IsNullOrWhiteSpace(tbRemoteIP.Text) || string.IsNullOrWhiteSpace(tbRemotePort.Text))
164             {
165                 MessageBox.Show("遠程IP和端口不能爲空!", "系統提示");
166                 return;
167             }
168 
169             if (string.IsNullOrWhiteSpace(tbSendMsg.Text))
170             {
171                 MessageBox.Show("發送的消息不能爲空!", "系統提示");
172                 return;
173             }
174 
175             if (!isLocalConneted)
176             {
177                 MessageBox.Show("請先建立本地連接!", "系統提示");
178                 return;
179             }
180 
181             
182             //構建本地遠程
183             if (cbIsRemoteAsLocal.Checked)//構建本地的遠程服務,本地處理
184             {
185                 if (!isRemoteCreated)
186                 {
187                     IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse(tbRemoteIP.Text), Convert.ToInt32(tbRemotePort.Text));//構建遠程端口
188                     remoteUdpcRecv = new UdpClient(remoteIpep);
189 
190                     //啓動遠程的監聽
191                     remoteThrRecv = new Thread(RemoteRecvMessage);
192                     remoteThrRecv.Start();
193 
194                     ShowMessage(tbRecvMsg, "[OS]:Remote UDP 監聽啓動完成!");
195                     isRemoteCreated = true;//遠程服務已啓動
196                 }
197                 else
198                 {
199                     //發送消息
200                 }
201 
202             }
203             else
204             {
205                 //發送消息,
206             }
207 
208             //發送遠程,這裏不做處理,直接調用udpcSend發送即可
209             thrSend = new Thread(new ParameterizedThreadStart(SendMessage));
210 
211             string[] param = new string[] { tbSendMsg.Text, tbRemoteIP.Text, tbRemotePort.Text };
212             thrSend.Start(param);
213 
214         }
215 
216         /// <summary>
217         /// 【本地遠程發送消息】
218         ///  20181021
219         /// </summary>
220         /// <param name="remoteIpep"></param>
221         private void RemoteSendMessage(IPEndPoint remoteIpep)
222         {
223             remoteUdpcSend = remoteUdpcRecv;
224 
225             byte[] msg = Encoding.Default.GetBytes("遠程已收到你的消息");
226 
227             remoteUdpcSend.Send(msg, msg.Length, remoteIpep);
228 
229             ShowMessage(tbRecvMsg, "[Remote Send]:" + "遠程已收到你的消息");
230         }
231 
232         /// <summary>
233         /// 【本地遠程接收信息】
234         ///  20181021
235         /// </summary>
236         private void RemoteRecvMessage()
237         {
238             IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);//接收任何來源的信息
239             while (true)
240             {
241                 byte[] byteRemoteRecv = remoteUdpcRecv.Receive(ref remoteIpep);
242                 string message = Encoding.Default.GetString(byteRemoteRecv);
243 
244                 //接收到信息
245                 if (byteRemoteRecv.Length > 0)
246                 {
247                     //remoteIpep.Address.ToString() 獲取發送源的IP
248                     ShowMessage(tbRecvMsg, "[Remote Recv]:" + remoteIpep.Address + ":" + remoteIpep.Port + "=" + message);
249                     
250                     RemoteSendMessage(remoteIpep);
251                 }
252 
253             }
254         }
255 
256         //更新顯示TextBox
257         delegate void ShowMessageDelegate(TextBox tb, string msg);
258         private void ShowMessage(TextBox tb, string msg)
259         {
260             if (tb.InvokeRequired)
261             {
262                 ShowMessageDelegate showMessageDelegate = ShowMessage;
263                 tb.Invoke(showMessageDelegate, new object[] { tb, msg });
264             }
265             else
266             {
267                 tb.Text += msg + "\r\n";
268             }
269         }
270 
271         //清空TextBox
272         delegate void ResetTextBoxDelegate(TextBox tb);
273         private void ResetTextBox(TextBox tb)
274         {
275             if (tb.InvokeRequired)
276             {
277                 ResetTextBoxDelegate resetTextBoxDelegate = ResetTextBox;
278                 tb.Invoke(resetTextBoxDelegate, new object[] { tb });
279             }
280             else
281             {
282                 tb.Text = "";
283             }
284         }
285 
286         /// <summary>
287         /// 【字符串轉16進制】
288         ///  20181021
289         /// </summary>
290         /// <param name="s"></param>
291         /// <returns></returns>
292         public byte[] HexStringToByteArray(string s)
293         {
294             if (s.Length == 0)
295                 throw new Exception("字符串長度爲0");
296             s = s.Replace(" ", "");
297             byte[] buffer = new byte[s.Length / 2];
298             for (int i = 0; i < s.Length; i += 2)
299                 buffer[i / 2] = Convert.ToByte(s.Substring(i, 2), 16);
300             return buffer;
301         }
302 
303         /// <summary>
304         /// 【字節數組轉換成十六進制字符串(不帶空格)】
305         ///  20181021
306         /// </summary>
307         /// <param name="data">要轉換的字節數組</param>
308         /// <returns>轉換後的字符串</returns>
309         public string ByteArrayToHexStringNoBlank(byte[] data)
310         {
311             StringBuilder sb = new StringBuilder(data.Length * 3);
312             foreach (byte b in data)
313                 sb.Append(Convert.ToString(b, 16).PadLeft(2, '0') + " ");
314             return sb.ToString().ToUpper();
315         }
316 
317         /// <summary>
318         /// 【窗體退出,關閉子線程】
319         ///  20181021
320         /// </summary>
321         /// <param name="sender"></param>
322         /// <param name="e"></param>
323         private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
324         {
325             Environment.Exit(0);
326         }
327 
328  
329 
330 
331     }
332 }

 

 

二、界面

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章