using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using Serilog; namespace Protocol376Simulator.Services { /// /// 网络服务类,负责TCP连接和网络通信 /// public class NetworkService : IDisposable { private readonly string _serverAddress; private readonly int _serverPort; private TcpClient _client; private NetworkStream _stream; private CancellationTokenSource _cancellationTokenSource; private readonly string _deviceIdentifier; /// /// 当接收到消息时触发 /// public event EventHandler MessageReceived; /// /// 当连接状态改变时触发 /// public event EventHandler ConnectionStatusChanged; /// /// 当发生错误时触发 /// public event EventHandler ErrorOccurred; /// /// 连接状态枚举 /// public enum ConnectionStatus { Disconnected, Connecting, Connected, Failed, Reconnecting } /// /// 是否连接到服务器 /// public bool IsConnected => _client != null && _client.Connected; /// /// 构造函数 /// /// 服务器地址 /// 服务器端口 /// 设备标识(用于日志) public NetworkService(string serverAddress, int serverPort, string deviceIdentifier) { _serverAddress = serverAddress; _serverPort = serverPort; _deviceIdentifier = deviceIdentifier; _cancellationTokenSource = new CancellationTokenSource(); } /// /// 连接到服务器 /// public async Task ConnectAsync() { try { // 如果已有连接,先断开 await DisconnectAsync(); // 重置取消标记 _cancellationTokenSource = new CancellationTokenSource(); // 触发状态改变事件 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Connecting); // 连接服务器 _client = new TcpClient(); Log.Information("{DeviceId} 正在连接到服务器 {ServerAddress}:{ServerPort}...", _deviceIdentifier, _serverAddress, _serverPort); await _client.ConnectAsync(_serverAddress, _serverPort); _stream = _client.GetStream(); Log.Information("{DeviceId} 已成功连接到服务器", _deviceIdentifier); // 触发状态改变事件 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Connected); // 启动接收消息任务 _ = StartReceiveMessagesAsync(_cancellationTokenSource.Token); } catch (Exception ex) { Log.Error(ex, "{DeviceId} 连接失败: {ErrorMessage}", _deviceIdentifier, ex.Message); // 触发错误事件 ErrorOccurred?.Invoke(this, ex); // 触发状态改变事件 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Failed); // 确保清理资源 _client?.Dispose(); _client = null; _stream = null; // 重新抛出异常,让调用者处理 throw; } } /// /// 断开连接 /// public async Task DisconnectAsync() { try { // 取消所有后台任务 _cancellationTokenSource?.Cancel(); // 关闭网络流和客户端 _stream?.Close(); _client?.Close(); // 等待一段时间确保资源释放 await Task.Delay(100); // 触发状态改变事件 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Disconnected); Log.Information("{DeviceId} 已断开连接", _deviceIdentifier); } catch (Exception ex) { Log.Error(ex, "{DeviceId} 断开连接时发生错误: {ErrorMessage}", _deviceIdentifier, ex.Message); ErrorOccurred?.Invoke(this, ex); } finally { _stream = null; _client = null; } } /// /// 发送消息 /// /// 要发送的消息字节数组 public async Task SendMessageAsync(byte[] message) { if (!IsConnected) { throw new InvalidOperationException("未连接到服务器,无法发送消息"); } try { await _stream.WriteAsync(message, 0, message.Length); await _stream.FlushAsync(); Log.Debug("{DeviceId} 发送消息: {HexMessage}", _deviceIdentifier, BitConverter.ToString(message).Replace("-", " ")); } catch (Exception ex) { Log.Error(ex, "{DeviceId} 发送消息失败: {ErrorMessage}", _deviceIdentifier, ex.Message); ErrorOccurred?.Invoke(this, ex); throw; } } /// /// 开始接收消息的后台任务 /// /// 取消标记 private async Task StartReceiveMessagesAsync(CancellationToken cancellationToken) { byte[] buffer = new byte[1024]; try { while (!cancellationToken.IsCancellationRequested && IsConnected) { // 读取消息长度 int bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken); if (bytesRead > 0) { // 创建一个新数组,只包含实际读取的字节 byte[] receivedMessage = new byte[bytesRead]; Array.Copy(buffer, receivedMessage, bytesRead); Log.Debug("{DeviceId} 收到消息: {HexMessage}", _deviceIdentifier, BitConverter.ToString(receivedMessage).Replace("-", " ")); // 触发消息接收事件 MessageReceived?.Invoke(this, receivedMessage); } else { // 读取0字节表示连接已关闭 Log.Warning("{DeviceId} 连接已关闭(服务器端断开)", _deviceIdentifier); break; } } } catch (OperationCanceledException) { // 任务被取消,正常退出 Log.Information("{DeviceId} 接收消息任务已取消", _deviceIdentifier); } catch (Exception ex) { if (!cancellationToken.IsCancellationRequested) { Log.Error(ex, "{DeviceId} 接收消息时发生错误: {ErrorMessage}", _deviceIdentifier, ex.Message); ErrorOccurred?.Invoke(this, ex); // 触发连接状态变更 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Failed); } } // 如果不是因为取消而退出循环,表示连接已断开 if (!cancellationToken.IsCancellationRequested && _client != null) { // 额外检查并确认连接状态 try { if (_client.Client != null && !_client.Client.Poll(0, SelectMode.SelectRead) || _client.Available != 0) { // 客户端仍然连接 return; } } catch { // 忽略额外的检查异常 } // 连接已断开 ConnectionStatusChanged?.Invoke(this, ConnectionStatus.Disconnected); } } /// /// 释放资源 /// public void Dispose() { _cancellationTokenSource?.Cancel(); _cancellationTokenSource?.Dispose(); _stream?.Dispose(); _client?.Dispose(); _cancellationTokenSource = null; _stream = null; _client = null; } } }