Socket客户端每10s发送Tcp连接请求到服务器

最近有个需求,需要走socket连接传输数据,我作为客户端需要给服务器进行数据推送,服务器可能不在线、异常等,需要自己判断处理 还不能影响目前代码逻辑。

于是……

class MQTTHostedService :  IHostedService
{
    
    private readonly SemaphoreSlim _hl7ConnectionLock = new SemaphoreSlim(1, 1);// 最多允许1个线程同时访问
    private TcpClient tcpClient;
    private Timer _timer;
    private NetworkStream stream;

    public Task StartAsync(CancellationToken cancellationToken)
    {
       _ = Task.Run(() => ExecuteAsyncHL7Send(cancellationToken));
    }

    public async Task ExecuteAsyncHL7Send(CancellationToken stoppingToken)
    {
       #region 方案二
       if (stoppingToken.IsCancellationRequested ||cacheProvider.GetHashString(CachingKeys.APP_SETTING_KEY, "IsHL7Send") != "1")
       {
           return;
       }

       string server = _configuration["HL7HostIP"];
       int port = int.Parse(_configuration["Port"]);

       _timer = new Timer(async _ =>
       {
           if (stoppingToken.IsCancellationRequested) return;

           if (!await _hl7ConnectionLock.WaitAsync(0)) return; // 避免并发执行
           try
           {
               await EnsureTcpConnectionAsync(server, port, stoppingToken);
           }
           catch (Exception ex)
           {
               Utils.WriteMsg($"连接异常: {ex.Message}", "ExecuteHL7", "MQTTHostedServiceHL7");
           }
           finally
           {
               _hl7ConnectionLock.Release();
           }
    }, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10));
    #endregion
}


private async Task EnsureTcpConnectionAsync(string server, int port, CancellationToken cancellationToken)
{
    if (tcpClient == null || !tcpClient.Connected)
    {
        DisposeTcpClient(); // 清理旧连接

        tcpClient = new TcpClient();

        var connectTask = tcpClient.ConnectAsync(server, port);
        var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5), cancellationToken);

        var completedTask = await Task.WhenAny(connectTask, timeoutTask);
        if (completedTask == connectTask && tcpClient.Connected)
        {
            stream = tcpClient.GetStream();
            Utils.WriteMsg($"已连接到服务器: {server}-{port}", "EnsureTcpConnectionAsync", "MQTTHostedServiceHL7");
        }
        else
        {
            Utils.WriteMsg($"连接超时或失败: {server}:{port}", "EnsureTcpConnectionAsync", "MQTTHostedServiceHL7");
            DisposeTcpClient();
        }
    }
}


private void DisposeTcpClient()
{
    try
    {
        stream?.Close();
        stream?.Dispose();
        stream = null;

        tcpClient?.Close();
        tcpClient?.Dispose();
        tcpClient = null;
    }
    catch (Exception ex)
    {
        Utils.WriteMsg($"释放连接时异常: {ex.Message}", "DisposeTcpClient", "MQTTHostedServiceHL7");
    }
}


private async void _mqttServer_ApplicationMessageNotConsumedAsync(MqttApplicationMessageReceivedEventArgs e)
{
   if (tcpClient!=null && tcpClient.Connected && stream != null)
   {
      try
      {
           byte[] iso8859_1 = Encoding.UTF8.GetBytes(data);
           await stream.WriteAsync(iso8859_1, 0, iso8859_1.Length);

           //byte[] buffer = new byte[1024];
           //int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
           //string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
           //Console.WriteLine("服务器响应: " + response);
       }
       catch (Exception ex)
       {
           Utils.WriteMsg($"Error '{e.ClientId}' {(ex.InnerException == null ? ex.Message : ex.InnerException.Message)}", "MqttServer_ApplicationMessageReceived", $"MQTTHostedServiceHL7");
       }
    }
}


}

 方案二支持多个ip及端口进行数据推送

public class Sender : IDisposable
{
    private readonly string _server;
    private readonly int _port;
    private TcpClient _tcpClient;
    private NetworkStream _stream;
    private readonly SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
    private readonly CancellationToken _token;
    private readonly int _connectTimeoutMs = 5000;
    private readonly int _sendTimeoutMs = 5000;

    public HL7Sender(string server, int port, CancellationToken token)
    {
        _server = server;
        _port = port;
        _token = token;
    }

    private async Task<bool> ConnectAsync()
    {
        DisposeConnection();

        _tcpClient = new TcpClient();
        var connectTask = _tcpClient.ConnectAsync(_server, _port);
        var timeoutTask = Task.Delay(_connectTimeoutMs, _token);

        var completed = await Task.WhenAny(connectTask, timeoutTask);
        if (completed == connectTask && _tcpClient.Connected)
        {
            _stream = _tcpClient.GetStream();
            _stream.ReadTimeout = _sendTimeoutMs;
            _stream.WriteTimeout = _sendTimeoutMs;
            return true;
        }
        DisposeConnection();
        return false;
    }

    private bool IsConnected()
    {
        try
        {
            if (_tcpClient == null) return false;
            if (!_tcpClient.Connected) return false;
            if (_tcpClient.Client.Poll(0, SelectMode.SelectRead))
            {
                byte[] buff = new byte[1];
                if (_tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
                {
                    return false; // socket closed
                }
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private async Task<bool> EnsureConnectedAsync()
    {
        if (IsConnected()) return true;

        const int maxRetries = 3;
        for (int i = 0; i < maxRetries; i++)
        {
            if (await ConnectAsync())
            {
                return true;
            }
            await Task.Delay(1000, _token);
        }
        return false;
    }

    public async Task<bool> SendMessageAsync(string message)
    {
        if (string.IsNullOrWhiteSpace(message)) return false;

        await _sendLock.WaitAsync(_token);
        try
        {
            if (!await EnsureConnectedAsync())
            {
                Utils.WriteMsg($"连接失败 {_server}:{_port}", "SendMessageAsync", $"MQTTHostedService");
                return false;
            }

            var bytes = Encoding.UTF8.GetBytes(message);
            await _stream.WriteAsync(bytes, 0, bytes.Length, _token);
            await _stream.FlushAsync(_token);
            return true;
        }
        catch (Exception ex)
        {
            Utils.WriteMsg($"发送异常 {_server}:{_port}", "SendMessageAsync", $"MQTTHostedService");
            DisposeConnection();
            return false;
        }
        finally
        {
            _sendLock.Release();
        }
    }

    private void DisposeConnection()
    {
        try
        {
            _stream?.Dispose();
            _tcpClient?.Close();
            _tcpClient?.Dispose();
        }
        catch { }
        finally
        {
            _stream = null;
            _tcpClient = null;
        }
    }

    public void Dispose()
    {
        DisposeConnection();
        _sendLock.Dispose();
    }
}
_senderI = new Sender(_configuration["HostI"], int.Parse(_configuration["PortI"]), CancellationToken.None);
_senderP = new Sender(_configuration["HostP"], int.Parse(_configuration["PortP"]), CancellationToken.None);

 

posted on 2025-04-07 14:29  白码一号  阅读(29)  评论(0)    收藏  举报