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);
浙公网安备 33010602011771号