[C#] 建立UDP连接、发送广播
说明:
通过建立本地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();
} }
}
二、界面

[C#] 建立UDP连接、发送广播的更多相关文章
- python实现建立udp通信
实现代码如下: #udp协议通信import socket,timeclass UdpConnect: def get_udp(self,ip,port,message): #建立udp连接 myso ...
- Android 通过局域网udp广播自动建立socket连接
Android开发中经常会用到socket通讯.由于项目需要,最近研究了一下这方面的知识. 需求是想通过wifi实现android移动设备和android平台的电视之间的文件传输与控制. 毫无疑问这中 ...
- 通过UDP建立TCP连接
解释 通过UDP广播查询服务器的IP地址,然后再建立TCP点对点连接. 应用场景 在服务器IP未知时,并且已知服务器与客户端明确在一个局域网或者允许组播的子网下. 通过UDP发现服务器地址然后再进行T ...
- 网游中的网络编程3:在UDP上建立虚拟连接
目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网络编程3:在UDP上建立虚拟连接 TODO 二.在UDP上建立虚拟连接 介绍 UDP是无连接的,一 ...
- udp发送广播消息
import socket if __name__ == '__main__': # 创建udpsocket udp_socket = socket.socket(socket.AF_INET, so ...
- UDP 单播、广播和多播
阅读目录(Content) 一.UDP广播 二.UDP多播 1.多播(组播)的概念 2.广域网的多播 三.UDP广播与单播 广播与单播的比较 使用UDP协议进行信息的传输之前不需要建议连接.换句话说就 ...
- UDP 单播、广播、多播
一.UDP广播 广播UDP与单播UDP的区别就是IP地址不同,广播使用广播地址255.255.255.255,将消息发送到在同一广播网络上的每个主机.值得强调的是:本地广播信息是不会被路由器转发.当然 ...
- HTTP协议用的TCP但是只建立单向连接
作者:IronTech链接:https://www.zhihu.com/question/20085992/answer/71742030来源:知乎著作权归作者所有,转载请联系作者获得授权. 下面的解 ...
- Linux 建立 TCP 连接的超时时间分析(解惑)
Linux 系统默认的建立 TCP 连接的超时时间为 127 秒,对于许多客户端来说,这个时间都太长了, 特别是当这个客户端实际上是一个服务的时候,更希望能够尽早失败,以便能够选择其它的可用服务重新尝 ...
随机推荐
- Java EE.JSP.概述
JSP最终会被转换成标准Servlet,该转换过程一般出现在第一次请求页面时. JSP页面的主要组成部分如下: HTML 脚本:嵌入Java代码 指令:从整体上控制Servlet的结构 动作:引入现有 ...
- AQS原理浅析
锁是最常用的同步方法之一,在高并发的环境下激烈的锁竞争会导致程序的性能下降,所以我们自然有必要深入的学习一下锁的相关知识. java的内置锁一直都是备受争议的,在JDK 1.6之前,synchroni ...
- 有不少朋友问我Halcon和Opencv的区别?
Halcon:机器视觉行业里知名的商业视觉库,非开源的,在国内市场份额处于第一,其提供了1500个多个API算子供开发人员使用,有些编程基础的都可以轻松的入门,其调试也是很方便的,断点单步运行,图像变 ...
- [算法]LeetCode 1.两数之和
LeetCode 1.两数之和(python) 1.朴素解法 最朴素的两个for循环大法: class Solution: def twoSum(self, nums: List[int], targ ...
- 序列化Serializable接口
一.序列化 1.什么是序列化? 序列化就是将对象的状态存储到特定存储介质中的过程,也就是将对象状态转换为可保持或传输格式的过程. 在序列化过程中,会将对象的公有成员.私有成员(包括类名),转换为字节流 ...
- 0 ElasticSearch
注意事项 需要jdk环境1.7以上 Elasticsearch Kibana 的下载地址统一为https://www.elastic.co/downloads/ 问题排查可以登录https://dis ...
- 【Android】Mac Android adb 配置
打开终端,输入下面命令: touch .bash_profile open -e .bash_profile 即新建 “.bash_profile” 文件,并会弹出 “.bash_profile” 文 ...
- 对API进行版本控制的重要性和实现方式
我在API设计中收到的最常见问题之一就是如何对API进行版本控制.虽然并非所有API都完全相同,但我发现在API版本控制方面,某些模式和实践适用于大多数团队.我已经将这些内容收集起来,下面将提供一些关 ...
- 【Java例题】2.7找零钱
7.为顾客找零钱时,希望选用的纸币张数最少. 例如73元,希望零钱的面值为五十元1张,二十元1张,一元3张. 设零钱面值有五十元.二十元.十元.五元和一元, 请编写程序,用户输入100以下的数, 计算 ...
- 《HTTP权威指南》--阅读笔记(一)
HTTP: HyperText Transfer Protocol 测试站点:http://www.joes-hardware.com URI包括URL和URN URI: Uniform Resour ...