176 lines
5.5 KiB
C#
176 lines
5.5 KiB
C#
|
|
using System;
|
||
|
|
using System.Net.NetworkInformation;
|
||
|
|
using UnityEngine;
|
||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
|
|
using System.Diagnostics;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Applies network settings per platform.
|
||
|
|
/// 跨平台网络配置器,支持 Windows netsh 和 Android WifiManager
|
||
|
|
/// </summary>
|
||
|
|
public static class NetworkConfigurator
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Apply DHCP or static IP to the active network interface.
|
||
|
|
/// </summary>
|
||
|
|
public static bool Apply(NetworkConfig config, string preferredInterface = null)
|
||
|
|
{
|
||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
|
|
var targetInterface = string.IsNullOrWhiteSpace(preferredInterface) ? GetPrimaryInterfaceName() : preferredInterface;
|
||
|
|
if (string.IsNullOrWhiteSpace(targetInterface))
|
||
|
|
{
|
||
|
|
Debug.LogWarning("No active network interface found to apply settings");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return config.Mode == NetworkMode.Dhcp
|
||
|
|
? ApplyDhcp(targetInterface)
|
||
|
|
: ApplyStatic(targetInterface, config);
|
||
|
|
#elif UNITY_ANDROID && !UNITY_EDITOR
|
||
|
|
return ApplyAndroid(config);
|
||
|
|
#else
|
||
|
|
Debug.Log($"[Simulated] Apply network: {config.Mode} {config.IPv4}/{config.Mask} gw:{config.Gateway} ");
|
||
|
|
return true;
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
#if UNITY_STANDALONE_WIN && !UNITY_EDITOR
|
||
|
|
private static bool ApplyDhcp(string interfaceName)
|
||
|
|
{
|
||
|
|
bool addr = RunNetsh($"interface ip set address name=\"{interfaceName}\" dhcp");
|
||
|
|
bool dns = RunNetsh($"interface ip set dns name=\"{interfaceName}\" dhcp");
|
||
|
|
return addr && dns;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool ApplyStatic(string interfaceName, NetworkConfig config)
|
||
|
|
{
|
||
|
|
string gateway = string.IsNullOrWhiteSpace(config.Gateway) ? "none" : config.Gateway;
|
||
|
|
bool addr = RunNetsh($"interface ip set address name=\"{interfaceName}\" static {config.IPv4} {config.Mask} {gateway} 1");
|
||
|
|
bool dns = ApplyDns(interfaceName, config);
|
||
|
|
return addr && dns;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool ApplyDns(string interfaceName, NetworkConfig config)
|
||
|
|
{
|
||
|
|
if (string.IsNullOrWhiteSpace(config.Dns1))
|
||
|
|
{
|
||
|
|
return RunNetsh($"interface ip set dns name=\"{interfaceName}\" dhcp");
|
||
|
|
}
|
||
|
|
|
||
|
|
bool primary = RunNetsh($"interface ip set dns name=\"{interfaceName}\" static {config.Dns1} primary");
|
||
|
|
bool secondary = true;
|
||
|
|
if (!string.IsNullOrWhiteSpace(config.Dns2))
|
||
|
|
{
|
||
|
|
secondary = RunNetsh($"interface ip add dns name=\"{interfaceName}\" {config.Dns2} index=2");
|
||
|
|
}
|
||
|
|
|
||
|
|
return primary && secondary;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static string GetPrimaryInterfaceName()
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
foreach (var ni in NetworkInterface.GetAllNetworkInterfaces())
|
||
|
|
{
|
||
|
|
if (ni.OperationalStatus != OperationalStatus.Up)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
return ni.Name;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
Debug.LogError($"Failed to query interfaces: {ex.Message}");
|
||
|
|
}
|
||
|
|
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool RunNetsh(string arguments)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
var psi = new ProcessStartInfo
|
||
|
|
{
|
||
|
|
FileName = "netsh",
|
||
|
|
Arguments = arguments,
|
||
|
|
CreateNoWindow = true,
|
||
|
|
UseShellExecute = false,
|
||
|
|
RedirectStandardError = true,
|
||
|
|
RedirectStandardOutput = true
|
||
|
|
};
|
||
|
|
|
||
|
|
using (var process = Process.Start(psi))
|
||
|
|
{
|
||
|
|
if (process == null)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
process.WaitForExit(5000);
|
||
|
|
|
||
|
|
if (!process.HasExited)
|
||
|
|
{
|
||
|
|
process.Kill();
|
||
|
|
Debug.LogWarning($"netsh timeout for args: {arguments}");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
string output = process.StandardOutput.ReadToEnd();
|
||
|
|
string error = process.StandardError.ReadToEnd();
|
||
|
|
bool success = process.ExitCode == 0;
|
||
|
|
|
||
|
|
if (!success)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"netsh failed ({process.ExitCode}) args:[{arguments}] error:[{error}] output:[{output}]");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.Log($"netsh success args:[{arguments}] output:[{output}]");
|
||
|
|
}
|
||
|
|
|
||
|
|
return success;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
Debug.LogError($"netsh exception: {ex.Message}");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
||
|
|
private static bool ApplyAndroid(NetworkConfig config)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
if (config.Mode == NetworkMode.Dhcp)
|
||
|
|
{
|
||
|
|
Debug.Log("[NetworkConfigurator] 在 Android 上应用 DHCP 配置");
|
||
|
|
return AndroidNetworkConfigurator.ApplyDhcp();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.Log("[NetworkConfigurator] 在 Android 上应用静态 IP 配置");
|
||
|
|
return AndroidNetworkConfigurator.ApplyStaticIP(
|
||
|
|
config.IPv4,
|
||
|
|
config.Mask,
|
||
|
|
config.Gateway,
|
||
|
|
config.Dns1,
|
||
|
|
config.Dns2
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (Exception ex)
|
||
|
|
{
|
||
|
|
Debug.LogError($"[NetworkConfigurator] Android 应用异常: {ex.Message}");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|