171 lines
6.0 KiB
C#
171 lines
6.0 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using YunDa.Server.ISMSTcp.Configuration;
|
|
using YunDa.Server.ISMSTcp.Interfaces;
|
|
|
|
namespace YunDa.Server.ISMSTcp.Services
|
|
{
|
|
/// <summary>
|
|
/// 自动连接服务 - 负责程序启动时自动连接TCP服务端
|
|
/// </summary>
|
|
public class AutoConnectionService : BackgroundService
|
|
{
|
|
private readonly ILogger<AutoConnectionService> _logger;
|
|
private readonly ITcpClient _tcpClient;
|
|
private readonly ISMSServerConfiguration _config;
|
|
private Timer? _connectionCheckTimer;
|
|
private readonly ZzDataCacheContainerInit _zzDataCacheContainerInit;
|
|
|
|
public AutoConnectionService(
|
|
ILogger<AutoConnectionService> logger,
|
|
ITcpClient tcpClient,
|
|
IOptions<ISMSServerConfiguration> config,
|
|
ZzDataCacheContainerInit zzDataCacheContainerInit)
|
|
{
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
_tcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient));
|
|
_config = config?.Value ?? throw new ArgumentNullException(nameof(config));
|
|
|
|
|
|
_zzDataCacheContainerInit = zzDataCacheContainerInit ?? throw new ArgumentNullException(nameof(zzDataCacheContainerInit));
|
|
|
|
zzDataCacheContainerInit.InitTcpService(_tcpClient);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 执行自动连接服务
|
|
/// </summary>
|
|
/// <param name="stoppingToken">停止令牌</param>
|
|
/// <returns>执行任务</returns>
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
try
|
|
{
|
|
if (!_config.EnableAutoConnect)
|
|
{
|
|
_logger.LogInformation("Auto connection is disabled in configuration");
|
|
return;
|
|
}
|
|
|
|
// 等待指定的延迟时间,让其他服务完全启动
|
|
_logger.LogInformation("Auto connection service starting in {Delay} seconds...",
|
|
_config.AutoConnectDelaySeconds);
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(_config.AutoConnectDelaySeconds), stoppingToken);
|
|
|
|
// 尝试初始连接
|
|
await AttemptInitialConnectionAsync(stoppingToken);
|
|
|
|
// 启动定期连接检查
|
|
StartConnectionHealthCheck(stoppingToken);
|
|
|
|
// 保持服务运行
|
|
while (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
_logger.LogInformation("Auto connection service was cancelled");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Auto connection service encountered an error");
|
|
}
|
|
finally
|
|
{
|
|
_connectionCheckTimer?.Dispose();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 尝试初始连接
|
|
/// </summary>
|
|
/// <param name="cancellationToken">取消令牌</param>
|
|
/// <returns>连接任务</returns>
|
|
private async Task AttemptInitialConnectionAsync(CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation("Attempting initial connection to {IP}:{Port}",
|
|
_config.ServerIP, _config.ServerPort);
|
|
|
|
await _tcpClient.ConnectAsync(_config.ServerIP, _config.ServerPort, cancellationToken);
|
|
|
|
if (_tcpClient.IsConnected)
|
|
{
|
|
_logger.LogInformation("Initial connection successful");
|
|
}
|
|
else
|
|
{
|
|
_logger.LogWarning("Initial connection failed, but reconnection mechanism should handle this");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error during initial connection attempt");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动连接健康检查
|
|
/// </summary>
|
|
/// <param name="cancellationToken">取消令牌</param>
|
|
private void StartConnectionHealthCheck(CancellationToken cancellationToken)
|
|
{
|
|
if (!_config.EnableConnectionRetry)
|
|
{
|
|
_logger.LogInformation("Connection health check is disabled");
|
|
return;
|
|
}
|
|
|
|
_logger.LogInformation("Starting connection health check with interval of 60 seconds");
|
|
|
|
_connectionCheckTimer = new Timer(async _ =>
|
|
{
|
|
if (cancellationToken.IsCancellationRequested) return;
|
|
|
|
try
|
|
{
|
|
await _tcpClient.EnsureConnectedAsync(cancellationToken);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error during connection health check");
|
|
}
|
|
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止服务时的清理工作
|
|
/// </summary>
|
|
/// <param name="cancellationToken">取消令牌</param>
|
|
/// <returns>停止任务</returns>
|
|
public override async Task StopAsync(CancellationToken cancellationToken)
|
|
{
|
|
_logger.LogInformation("Auto connection service is stopping...");
|
|
|
|
_connectionCheckTimer?.Dispose();
|
|
_connectionCheckTimer = null;
|
|
|
|
await base.StopAsync(cancellationToken);
|
|
|
|
_logger.LogInformation("Auto connection service stopped");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 释放资源
|
|
/// </summary>
|
|
public override void Dispose()
|
|
{
|
|
_connectionCheckTimer?.Dispose();
|
|
base.Dispose();
|
|
}
|
|
}
|
|
}
|