WorkCamera/client/WorkCameraExport/Services/NetworkMonitor.cs
2026-01-05 23:58:56 +08:00

168 lines
5.3 KiB
C#

using System.Net.NetworkInformation;
using WorkCameraExport.Services.Interfaces;
namespace WorkCameraExport.Services
{
/// <summary>
/// 网络监控服务 - 负责检测网络连接状态
/// </summary>
public class NetworkMonitor : IDisposable
{
private readonly ILogService? _logService;
private bool _isNetworkAvailable;
private bool _disposed;
/// <summary>
/// 网络状态变化事件
/// </summary>
public event EventHandler<NetworkStatusChangedEventArgs>? NetworkStatusChanged;
/// <summary>
/// 当前网络是否可用
/// </summary>
public bool IsNetworkAvailable => _isNetworkAvailable;
public NetworkMonitor(ILogService? logService = null)
{
_logService = logService;
_isNetworkAvailable = NetworkInterface.GetIsNetworkAvailable();
// 订阅网络状态变化事件
NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
}
/// <summary>
/// 检查网络是否可用
/// </summary>
public bool CheckNetworkAvailability()
{
try
{
_isNetworkAvailable = NetworkInterface.GetIsNetworkAvailable();
return _isNetworkAvailable;
}
catch (Exception ex)
{
_logService?.Error("检查网络状态失败", ex);
return false;
}
}
/// <summary>
/// 检查是否可以连接到指定服务器
/// </summary>
public async Task<bool> CheckServerConnectivityAsync(string serverUrl, int timeoutMs = 5000)
{
if (string.IsNullOrWhiteSpace(serverUrl))
{
return false;
}
try
{
using var httpClient = new HttpClient
{
Timeout = TimeSpan.FromMilliseconds(timeoutMs)
};
var uri = new Uri(serverUrl);
var response = await httpClient.GetAsync($"{uri.Scheme}://{uri.Host}:{uri.Port}/");
return response.IsSuccessStatusCode ||
response.StatusCode == System.Net.HttpStatusCode.Unauthorized ||
response.StatusCode == System.Net.HttpStatusCode.NotFound;
}
catch (Exception ex)
{
_logService?.Warn($"无法连接到服务器 {serverUrl}: {ex.Message}");
return false;
}
}
/// <summary>
/// 使用 Ping 检查网络连通性
/// </summary>
public async Task<bool> PingAsync(string host = "8.8.8.8", int timeoutMs = 3000)
{
try
{
using var ping = new Ping();
var reply = await ping.SendPingAsync(host, timeoutMs);
return reply.Status == IPStatus.Success;
}
catch (Exception ex)
{
_logService?.Warn($"Ping 失败: {ex.Message}");
return false;
}
}
/// <summary>
/// 网络可用性变化事件处理
/// </summary>
private void OnNetworkAvailabilityChanged(object? sender, NetworkAvailabilityEventArgs e)
{
var previousState = _isNetworkAvailable;
_isNetworkAvailable = e.IsAvailable;
if (previousState != _isNetworkAvailable)
{
_logService?.Info($"网络状态变化: {(e.IsAvailable ? "" : "")}");
NetworkStatusChanged?.Invoke(this, new NetworkStatusChangedEventArgs(e.IsAvailable));
}
}
/// <summary>
/// 网络地址变化事件处理
/// </summary>
private void OnNetworkAddressChanged(object? sender, EventArgs e)
{
var newState = NetworkInterface.GetIsNetworkAvailable();
var previousState = _isNetworkAvailable;
_isNetworkAvailable = newState;
if (previousState != newState)
{
_logService?.Info($"网络地址变化,当前状态: {(newState ? "" : "")}");
NetworkStatusChanged?.Invoke(this, new NetworkStatusChangedEventArgs(newState));
}
}
#region IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
NetworkChange.NetworkAvailabilityChanged -= OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged -= OnNetworkAddressChanged;
}
_disposed = true;
}
}
#endregion
}
/// <summary>
/// 网络状态变化事件参数
/// </summary>
public class NetworkStatusChangedEventArgs : EventArgs
{
public bool IsAvailable { get; }
public NetworkStatusChangedEventArgs(bool isAvailable)
{
IsAvailable = isAvailable;
}
}
}