Files

86 lines
2.4 KiB
C#
Raw Permalink Normal View History

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using PCL.Core.IO.Net;
namespace PCL.Core.Link;
public class BroadcastLocal(string description, int localPort) : IDisposable
{
private Socket? _broadcastSocket;
private CancellationTokenSource? _cts;
private bool _isRunning;
public void Start()
{
if (_isRunning) return;
_cts = new CancellationTokenSource();
_isRunning = true;
// 启动 UDP 广播任务
_ = Task.Run(() => _RunUdpBroadcastAsync(_cts.Token), _cts.Token);
Console.WriteLine($"开始向本地 Minecraft 客户端广播,端口: {localPort}");
}
public void Stop()
{
if (!_isRunning) return;
_cts?.Cancel();
_isRunning = false;
_broadcastSocket?.SafeClose();
Console.WriteLine("停止向本地 Minecraft 客户端广播");
}
private async Task _RunUdpBroadcastAsync(CancellationToken cancellationToken)
{
try
{
_broadcastSocket = new Socket(SocketType.Dgram, ProtocolType.Udp)
{
DualMode = true
};
var buffer = Encoding.UTF8.GetBytes($"[MOTD]{description}[/MOTD][AD]{localPort}[/AD]");
// 向本地地址发送,而不是广播地址
var localEndpoint = new IPEndPoint(IPAddress.Loopback, 4445);
while (!cancellationToken.IsCancellationRequested)
{
try
{
await _broadcastSocket.SendToAsync(new ArraySegment<byte>(buffer), SocketFlags.None, localEndpoint);
await Task.Delay(1500, cancellationToken);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
Console.WriteLine($"UDP 本地广播错误: {ex.Message}");
await Task.Delay(5000, cancellationToken); // 出错后等待 5 秒再重试
}
}
}
catch (Exception ex)
{
Console.WriteLine($"UDP 本地广播任务发生错误: {ex.Message}");
}
}
public void Dispose()
{
Stop();
_cts?.Dispose();
_broadcastSocket.SafeClose();
GC.SuppressFinalize(this);
}
}