说明:

  通过建立本地UdpClient与远程UdpClient进行通讯,亦可直接发送到其他已存在的远程端。

  基本原理:构建一个本地的udpcSend实例,开启多线程进行监听,然后再发送广播。

  案例有字节数组与十六进制字符串相互转换的方法。

一、案例源码

  窗体的主要代码:FrmMain.cs

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace NetworkService
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent(); //string msg = "FF FB 0F";
//byte[] bytes = Encoding.Default.GetBytes(msg); //string res = "";
//for (int i = 0; i < bytes.Length; i++)
//{
// res += bytes[i].ToString();
//}
//MessageBox.Show(res); } //本地收发UDPClient实例
private UdpClient udpcSend;
private UdpClient udpcRecv;
private bool isLocalConneted = false;//本地是否已连接
private Thread thrRecv;//本地监听接收线程 /// <summary>
/// 【构建本地连接】
/// 20181021
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnConnect_Click(object sender, EventArgs e)
{
if (cbProtocol.SelectedIndex != )
{
MessageBox.Show("请暂时选择UDP协议!", "系统提示");
return;
} if (string.IsNullOrWhiteSpace(tbLocalIP.Text) || string.IsNullOrWhiteSpace(tbLocalPort.Text))
{
MessageBox.Show("请填写本地IP和端口", "系统提示");
return;
} if (!isLocalConneted)//构建本地连接
{
IPEndPoint localIpep = new IPEndPoint(IPAddress.Parse(tbLocalIP.Text), Convert.ToInt32(tbLocalPort.Text));
udpcSend = new UdpClient(localIpep); btnConnect.Text = "断开";
isLocalConneted = true; //启动监听接收信息
BeginListenRecv();
}
else//断开本地连接
{
//关闭监听线程
thrRecv.Abort();
udpcRecv.Close(); udpcSend.Close();
btnConnect.Text = "连接";
isLocalConneted = false; ShowMessage(tbRecvMsg, "[OS]:UDP监听已成功关闭");
}
} /// <summary>
/// 【开始监听】
/// 20181021
/// </summary>
private void BeginListenRecv()
{
udpcRecv = udpcSend;//接收与发送使用同一个实例 thrRecv = new Thread(ReceiveMessage);
thrRecv.Start(); ShowMessage(tbRecvMsg, "[OS]:Local UDP 监听已成功启动"); } /// <summary>
/// 【接收信息】
/// 20181021
/// </summary>
private void ReceiveMessage()
{
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, );//接收任何来源的信息
while (true)
{
byte[] byteRecv = udpcRecv.Receive(ref remoteIpep);
string message = ByteArrayToHexStringNoBlank(byteRecv); //remoteIpep.Address.ToString() 获取发送源的IP
ShowMessage(tbRecvMsg, "[Local Recv]:" + remoteIpep.Address + ":" + remoteIpep.Port + "=" + message); } } /// <summary>
/// 【发送消息】
/// 20181021
/// </summary>
/// <param name="obj"></param>
private void SendMessage(object obj)
{
string[] data = (string[])obj; //字符串转16进制
byte[] sendBytes = HexStringToByteArray(data[]); //发送到远程IP和端口
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse(data[]), Convert.ToInt32(data[])); udpcSend.Send(sendBytes, sendBytes.Length, remoteIpep); ShowMessage(tbRecvMsg, "[Local Send]:" + data[]);
ResetTextBox(tbSendMsg);
} //构建远程服务的收发实例
private UdpClient remoteUdpcSend;
private UdpClient remoteUdpcRecv;
private Thread remoteThrRecv; private Thread thrSend;
private bool isRemoteCreated = false;
/// <summary>
/// 【发送消息】
/// 20181021
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(tbRemoteIP.Text) || string.IsNullOrWhiteSpace(tbRemotePort.Text))
{
MessageBox.Show("远程IP和端口不能为空!", "系统提示");
return;
} if (string.IsNullOrWhiteSpace(tbSendMsg.Text))
{
MessageBox.Show("发送的消息不能为空!", "系统提示");
return;
} if (!isLocalConneted)
{
MessageBox.Show("请先建立本地连接!", "系统提示");
return;
} //构建本地远程
if (cbIsRemoteAsLocal.Checked)//构建本地的远程服务,本地处理
{
if (!isRemoteCreated)
{
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Parse(tbRemoteIP.Text), Convert.ToInt32(tbRemotePort.Text));//构建远程端口
remoteUdpcRecv = new UdpClient(remoteIpep); //启动远程的监听
remoteThrRecv = new Thread(RemoteRecvMessage);
remoteThrRecv.Start(); ShowMessage(tbRecvMsg, "[OS]:Remote UDP 监听启动完成!");
isRemoteCreated = true;//远程服务已启动
}
else
{
//发送消息
} }
else
{
//发送消息,
} //发送远程,这里不做处理,直接调用udpcSend发送即可
thrSend = new Thread(new ParameterizedThreadStart(SendMessage)); string[] param = new string[] { tbSendMsg.Text, tbRemoteIP.Text, tbRemotePort.Text };
thrSend.Start(param); } /// <summary>
/// 【本地远程发送消息】
/// 20181021
/// </summary>
/// <param name="remoteIpep"></param>
private void RemoteSendMessage(IPEndPoint remoteIpep)
{
remoteUdpcSend = remoteUdpcRecv; byte[] msg = Encoding.Default.GetBytes("远程已收到你的消息"); remoteUdpcSend.Send(msg, msg.Length, remoteIpep); ShowMessage(tbRecvMsg, "[Remote Send]:" + "远程已收到你的消息");
} /// <summary>
/// 【本地远程接收信息】
/// 20181021
/// </summary>
private void RemoteRecvMessage()
{
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, );//接收任何来源的信息
while (true)
{
byte[] byteRemoteRecv = remoteUdpcRecv.Receive(ref remoteIpep);
string message = Encoding.Default.GetString(byteRemoteRecv); //接收到信息
if (byteRemoteRecv.Length > )
{
//remoteIpep.Address.ToString() 获取发送源的IP
ShowMessage(tbRecvMsg, "[Remote Recv]:" + remoteIpep.Address + ":" + remoteIpep.Port + "=" + message); RemoteSendMessage(remoteIpep);
} }
} //更新显示TextBox
delegate void ShowMessageDelegate(TextBox tb, string msg);
private void ShowMessage(TextBox tb, string msg)
{
if (tb.InvokeRequired)
{
ShowMessageDelegate showMessageDelegate = ShowMessage;
tb.Invoke(showMessageDelegate, new object[] { tb, msg });
}
else
{
tb.Text += msg + "\r\n";
}
} //清空TextBox
delegate void ResetTextBoxDelegate(TextBox tb);
private void ResetTextBox(TextBox tb)
{
if (tb.InvokeRequired)
{
ResetTextBoxDelegate resetTextBoxDelegate = ResetTextBox;
tb.Invoke(resetTextBoxDelegate, new object[] { tb });
}
else
{
tb.Text = "";
}
} /// <summary>
/// 【字符串转16进制】
/// 20181021
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public byte[] HexStringToByteArray(string s)
{
if (s.Length == )
throw new Exception("字符串长度为0");
s = s.Replace(" ", "");
byte[] buffer = new byte[s.Length / ];
for (int i = ; i < s.Length; i += )
buffer[i / ] = Convert.ToByte(s.Substring(i, ), );
return buffer;
} /// <summary>
/// 【字节数组转换成十六进制字符串(不带空格)】
/// 20181021
/// </summary>
/// <param name="data">要转换的字节数组</param>
/// <returns>转换后的字符串</returns>
public string ByteArrayToHexStringNoBlank(byte[] data)
{
StringBuilder sb = new StringBuilder(data.Length * );
foreach (byte b in data)
sb.Append(Convert.ToString(b, ).PadLeft(, '') + " ");
return sb.ToString().ToUpper();
} /// <summary>
/// 【窗体退出,关闭子线程】
/// 20181021
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit();
} }
}

二、界面

  

最新文章

  1. Membership三步曲之入门篇 - Membership基础示例
  2. 深入探讨:标签(Tag)的各种设计方案
  3. VC++ Debugger Tips[转]
  4. JSP中脚本、声明和表达式的本质区别
  5. HTTP协议及HTTP包
  6. Session中StateServer的使用方法
  7. 以css伪类为基础,引发的选择器讨论 [新手向]
  8. Day04 (黑客成长日记) 集合记录
  9. day18_雷神_django第一天
  10. Android MediaPlayer SeekTo 在 8.0 版本上优化说明
  11. Hadoop生态圈-Zookeeper的工作原理分析
  12. Null和undefined的区别?
  13. Python中的and/or
  14. macos安装postman
  15. scp命令简单应用
  16. Fine Tuning
  17. 1. Linux内核的配置与裁减:
  18. 在上传文件时候 request.setCharset对文件名有效 对普通文本域无效 需要通过手动转换编码方式编码
  19. bzoj3473字符串&amp;bzoj3277串
  20. python selenium firefox使用

热门文章

  1. PHP使用array_unique对二维数组去重处理
  2. mongodb数据库常用操作的整理
  3. Spark 源码分析系列
  4. js里的Document对象介绍
  5. 【Java】设置 JPanel 宽度
  6. 使用eclipse编写和运行java程序(基础)
  7. 20190803 NOIP模拟测试12「斐波那契(fibonacci)&#183; 数颜色 &#183; 分组 」
  8. 3. 源码分析---SOFARPC客户端服务调用
  9. Selenium+java - Ajax浮动框处理
  10. template.demo.js