[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 + "
";
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 }

二、界面

  

原文地址:https://www.cnblogs.com/reader/p/9835917.html