UDP协议通信
UDP(User Datagram Protocol,用户数据报协议)是一种网络传输协议,属于传输层(TCP/IP 协议族)。它的主要特点和在 C# 中的表现:
- 无连接:发送方与接收方之间不建立连接,直接发送数据报(datagram)。
- 不可靠:不保证到达、不保证顺序、不做重传或确认;丢包或乱序需由应用层处理。
- 低开销、延迟小:相比 TCP 更轻量,适合实时性要求高但能容忍部分丢包的场景(语音、视频、在线游戏、广播/多播)。
- 报文边界保留:UDP 按数据报发送/接收,接收端能知道每次发送的报文边界。
在 C# 中常用类与用法:
- UdpClient:封装较高层次的 UDP 操作,提供 Send/Receive 和异步 SendAsync/ReceiveAsync,适合大多数场景。
- Socket:底层套接字 API(SocketType.Dgram, ProtocolType.Udp),用于需要精细控制(多播、广播、Socket 选项、性能调优)时。
- 基本流程:接收端 bind 到本地端口并调用 Receive/ReceiveAsync/ReceiveFromAsync;发送端可直接 Send/SendAsync/SendTo(通常无需先 bind)。
.xaml
<Window x:Class="StudyUdp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:StudyUdp" mc:Ignorable="d" Title="Udp(用socket实现)" Height="450" Width="800"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1.5*"></ColumnDefinition> <ColumnDefinition Width="4*"></ColumnDefinition> </Grid.ColumnDefinitions> <!--左边--> <Grid Background="Azure"> <Grid.RowDefinitions> <RowDefinition Height="auto"></RowDefinition> <RowDefinition Height="auto"></RowDefinition> <RowDefinition Height="auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition ></ColumnDefinition> <ColumnDefinition ></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,5">本机主机地址</TextBlock> <TextBox x:Name="txtIP" Grid.Column="1" Width="150" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,5,5">127.0.0.1</TextBox> <TextBlock Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,5,5">本机主机端口</TextBlock> <TextBox x:Name="txtPort" Grid.Row="1" Grid.Column="1" Width="100" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,5,5">8888</TextBox> <Button x:Name="BtnOpen" Grid.Row="5" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,10,5" Click="BtnOpen_Click">打开</Button> <Button x:Name="BtnClose" Grid.Row="5" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,10,5" Visibility="Collapsed" Click="BtnClose_Click">关闭</Button> </Grid> <!--右边--> <Grid Grid.Column="1"> <Grid.RowDefinitions> <RowDefinition Height="auto"></RowDefinition> <RowDefinition Height="auto"></RowDefinition> </Grid.RowDefinitions> <RichTextBox Height="300" x:Name="txtShowContent" VerticalScrollBarVisibility="Visible"></RichTextBox> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="2*"></ColumnDefinition> <ColumnDefinition Width="1*"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <StackPanel Grid.ColumnSpan="2" Orientation="Horizontal" > <TextBlock Margin="0,0,5,0">接收方信息</TextBlock> <TextBlock Margin="0,0,5,0">IP:</TextBlock> <TextBox x:Name="txtRecIP" Text="127.0.0.1" Width="150" Margin="0,0,5,0"></TextBox> <TextBlock Margin="0,0,5,0">端口:</TextBlock> <TextBox x:Name="txtRecPort" Width="100"></TextBox> </StackPanel> <TextBox Height="80" x:Name="txtSendContent" Grid.Row="1"></TextBox> <Button Grid.Column="1" Grid.Row="1" x:Name="BtnSend" Click="BtnSend_Click">发送</Button> </Grid> </Grid> </Grid> </Window>
.xaml.cs
using System.Net; using System.Net.Sockets; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using static System.Net.Mime.MediaTypeNames; namespace StudyUdp; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { Socket client; public MainWindow() { InitializeComponent(); } /// <summary> /// 打开 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnOpen_Click(object sender, RoutedEventArgs e) { try { #region 用socket实现 client = new Socket(SocketType.Dgram, ProtocolType.Udp); string ip = txtIP.Text; int port = Convert.ToInt32(txtPort.Text); client.Bind(new IPEndPoint(IPAddress.Parse(ip), port)); BtnOpen.Visibility = Visibility.Collapsed; BtnClose.Visibility = Visibility.Visible; AppendTxt("打开成功", Colors.Green); #endregion #region 接收信息 Task.Run(async () => { while (true) { _ = Dispatcher.Invoke(async () => { //1、不需要知道谁发的 2、需要知道是谁发的 byte[] recBytes = new byte[1024]; IPEndPoint ipEp = new IPEndPoint(IPAddress.Any, 0); var result = await client.ReceiveFromAsync(recBytes, ipEp); if (result.ReceivedBytes > 0)//有数据 { string recMsg = Encoding.UTF8.GetString(recBytes); AppendTxt($"来自{result.RemoteEndPoint}的信息:{recMsg}", Colors.Blue); } }); await Task.Delay(1000); } }); #endregion } catch (Exception) { BtnOpen.Visibility = Visibility.Visible; BtnClose.Visibility = Visibility.Collapsed; AppendTxt("打开异常", Colors.Red); } } /// <summary> /// 关闭 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnClose_Click(object sender, RoutedEventArgs e) { if (client != null) { client.Close(); BtnOpen.Visibility = Visibility.Visible; BtnClose.Visibility = Visibility.Collapsed; AppendTxt("已关闭", Colors.Red); } } /// <summary> /// 发送 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnSend_Click(object sender, RoutedEventArgs e) { try { if (client != null) { string sendMsg = txtSendContent.Text; byte[] sendBytes = Encoding.UTF8.GetBytes(sendMsg); //1、发送给所有连接自己的Client 2、给指定的终端发送信息 client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse(txtRecIP.Text), Convert.ToInt32(txtRecPort.Text))); AppendTxt($"发送信息:{sendMsg}", Colors.Black); #region 广播发送 //string sendMsg = txtSendContent.Text; //byte[] sendBytes = Encoding.UTF8.GetBytes(sendMsg); ////1、发送给所有连接自己的Client 2、给指定的终端发送信息 //client.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.Broadcast,true); ////client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse("192.168.0.255"), 9999)); //client.SendTo(sendBytes, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 9999)); //AppendTxt($"发送信息:{sendMsg}", Colors.Black); #endregion } } catch (Exception) { AppendTxt($"发送信息异常", Colors.Red); } } FlowDocument doc = new FlowDocument(); /// <summary> /// 追加文本 /// </summary> /// <param name="txt"></param> /// <param name="txtColor">文字颜色</param> private void AppendTxt(string txt, Color txtColor) { var p = new Paragraph(); // Paragraph 类似于 html 的 P 标签 var r = new Run($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {txt}"); // Run 是一个 Inline 的标签 p.Inlines.Add(r); p.Foreground = new SolidColorBrush(txtColor);//设置字体颜色 doc.Blocks.Add(p); txtShowContent.Document = doc; txtShowContent.ScrollToEnd(); } }

浙公网安备 33010602011771号