140 lines
4.2 KiB
C#
140 lines
4.2 KiB
C#
using System;
|
||
using System.Net;
|
||
using System.Net.NetworkInformation;
|
||
using System.Net.Sockets;
|
||
using System.Text;
|
||
using System.Threading;
|
||
using UnityEngine;
|
||
|
||
public class BroadcastServer : MonoBehaviour
|
||
{
|
||
private UdpClient udpClient; // 用于发送广播的UDP客户端
|
||
private Thread broadcastThread; // 广播线程
|
||
private volatile bool isRunning = true; // 线程安全的运行标志
|
||
|
||
[Header("网络配置")]
|
||
[SerializeField] private int broadcastPort = 9999; // UDP广播端口
|
||
[SerializeField] private float broadcastInterval = 1f; // 广播间隔(秒)
|
||
[SerializeField] private string preferredNetworkInterface = ""; // 优先网络接口(可选)
|
||
|
||
[Header("日志级别")]
|
||
[SerializeField] private LogLevel logLevel = LogLevel.Verbose; // 日志级别控制
|
||
public enum LogLevel { None, Minimal, Verbose }
|
||
|
||
// 脚本启动时调用
|
||
void Start()
|
||
{
|
||
try
|
||
{
|
||
udpClient = new UdpClient();
|
||
udpClient.EnableBroadcast = true;
|
||
broadcastThread = new Thread(BroadcastIP);
|
||
broadcastThread.Start();
|
||
if (logLevel != LogLevel.None)
|
||
{
|
||
Debug.Log($"广播服务器已启动,端口: {broadcastPort}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"初始化UDP客户端失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// 广播显示端服务器的IP地址
|
||
private void BroadcastIP()
|
||
{
|
||
string localIP = GetLocalIPAddress();
|
||
if (string.IsNullOrEmpty(localIP))
|
||
{
|
||
Debug.LogError("无法获取本地IP地址,广播停止");
|
||
return;
|
||
}
|
||
|
||
string message = $"ServerIP:{localIP}";
|
||
byte[] data = Encoding.UTF8.GetBytes(message);
|
||
IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, broadcastPort);
|
||
|
||
while (isRunning)
|
||
{
|
||
try
|
||
{
|
||
udpClient.Send(data, data.Length, endPoint);
|
||
if (logLevel == LogLevel.Verbose)
|
||
{
|
||
Debug.Log($"广播IP: {message}");
|
||
}
|
||
Thread.Sleep((int)(broadcastInterval * 1000));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
if (logLevel != LogLevel.None)
|
||
{
|
||
Debug.LogError($"广播错误: {ex.Message}");
|
||
}
|
||
Thread.Sleep(5000);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取本地IP地址,排除回环地址
|
||
private string GetLocalIPAddress()
|
||
{
|
||
try
|
||
{
|
||
foreach (var networkInterface in NetworkInterface.GetAllNetworkInterfaces())
|
||
{
|
||
if (networkInterface.OperationalStatus != OperationalStatus.Up ||
|
||
networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback)
|
||
continue;
|
||
|
||
if (!string.IsNullOrEmpty(preferredNetworkInterface) && networkInterface.Name != preferredNetworkInterface)
|
||
continue;
|
||
|
||
foreach (var unicastIPAddress in networkInterface.GetIPProperties().UnicastAddresses)
|
||
{
|
||
if (unicastIPAddress.Address.AddressFamily == AddressFamily.InterNetwork)
|
||
{
|
||
string ip = unicastIPAddress.Address.ToString();
|
||
if (!ip.StartsWith("127."))
|
||
{
|
||
if (logLevel == LogLevel.Verbose)
|
||
{
|
||
Debug.Log($"选择IP: {ip} (接口: {networkInterface.Name})");
|
||
}
|
||
return ip;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Debug.LogError("未找到有效的IPv4地址");
|
||
return "";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"获取IP地址错误: {ex.Message}");
|
||
return "";
|
||
}
|
||
}
|
||
|
||
// 应用程序退出时清理资源
|
||
private void OnApplicationQuit()
|
||
{
|
||
isRunning = false;
|
||
udpClient?.Close();
|
||
if (broadcastThread != null && broadcastThread.IsAlive)
|
||
{
|
||
broadcastThread.Join(1000);
|
||
}
|
||
if (logLevel != LogLevel.None)
|
||
{
|
||
Debug.Log("广播服务器已停止");
|
||
}
|
||
}
|
||
|
||
// 确保资源在销毁时清理
|
||
private void OnDestroy()
|
||
{
|
||
OnApplicationQuit();
|
||
}
|
||
} |