using DeviceService.Core;
using System.IO;
using System.IO.Pipes;
using System.Text.Json;
namespace DeviceService.Service.NamePipe
{
///
/// 基于命名管道的服务端实现(Message 模式)。
/// 启动后持续监听客户端连接,收到的每条消息通过 事件上抛,
/// 并携带可回写数据的 实例。
///
public class NamePipeService : IService, IDisposable
{
/// 默认允许的最大管道实例数(即最大并发连接数)。
public const int DefaultMaxInstances = 254;
/// 停止服务时等待后台任务结束的最长时间。
private static readonly TimeSpan StopTimeout = TimeSpan.FromSeconds(3);
private readonly string _pipeName;
private readonly int _maxInstances;
private readonly object _sync = new object();
private readonly Dictionary _clients = new Dictionary();
private CancellationTokenSource? _cts;
private NamedPipeServerStream? _listenStream;
private Task? _acceptTask;
private bool _running;
private bool _disposed;
/// 管道名称,为空时在 Start 阶段校验失败。
/// 最大并发连接数。
public NamePipeService(string? pipeName = null, int maxInstances = DefaultMaxInstances)
{
if (maxInstances <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxInstances), "最大实例数必须大于 0。");
}
_pipeName = pipeName ?? string.Empty;
_maxInstances = maxInstances;
}
public event EventHandler? ClientConnected;
public event EventHandler? ClientDisConnected;
public event EventHandler? DataReceived;
/// 管道名称。
public string PipeName => _pipeName;
/// 服务是否处于监听状态。
public bool IsRunning
{
get
{
lock (_sync)
{
return _running;
}
}
}
/// 当前已连接的客户端数量。
public int ClientCount
{
get
{
lock (_sync)
{
return _clients.Count;
}
}
}
public bool Start(out string msg)
{
lock (_sync)
{
if (_disposed)
{
msg = "服务已释放,无法启动。";
return false;
}
if (_running)
{
msg = "服务已处于运行状态。";
return false;
}
if (string.IsNullOrWhiteSpace(_pipeName))
{
msg = "管道名称未设置,无法启动。";
return false;
}
NamedPipeServerStream listenStream;
try
{
listenStream = CreatePipeStream();
}
catch (Exception ex)
{
msg = $"创建命名管道 \"{_pipeName}\" 失败:{ex.Message}";
return false;
}
var cts = new CancellationTokenSource();
_cts = cts;
_listenStream = listenStream;
_running = true;
_acceptTask = Task.Run(() => AcceptLoopAsync(listenStream, cts.Token));
}
msg = $"命名管道 \"{_pipeName}\" 已启动监听。";
return true;
}
public bool Stop(out string msg)
{
Task? acceptTask;
List clientTasks = new List();
lock (_sync)
{
if (!_running)
{
msg = "服务未运行。";
return false;
}
_running = false;
acceptTask = _acceptTask;
_acceptTask = null;
try
{
_cts?.Cancel();
}
catch
{
// 忽略取消过程中的异常
}
try
{
_listenStream?.Dispose();
}
catch
{
// 忽略关闭监听流的异常
}
_listenStream = null;
// 关闭所有客户端连接,使阻塞中的读取立即结束
foreach (KeyValuePair item in _clients)
{
try
{
item.Key.Dispose();
}
catch
{
// 忽略单个连接的关闭异常
}
clientTasks.Add(item.Value);
}
_clients.Clear();
_cts?.Dispose();
_cts = null;
}
try
{
acceptTask?.Wait(StopTimeout);
if (clientTasks.Count > 0)
{
Task.WaitAll(clientTasks.ToArray(), StopTimeout);
}
}
catch (AggregateException)
{
// 后台任务在校验/取消阶段抛出的异常无需向上传播
}
msg = "服务已停止。";
return true;
}
private NamedPipeServerStream CreatePipeStream()
{
var pipe = new NamedPipeServerStream(
_pipeName,
PipeDirection.InOut,
_maxInstances,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous);
pipe.ReadMode = PipeTransmissionMode.Message;
return pipe;
}
///
/// 连接接受循环:每接受一个连接就交给独立的处理任务,并准备下一个管道实例继续监听。
///
private async Task AcceptLoopAsync(NamedPipeServerStream initial, CancellationToken token)
{
NamedPipeServerStream? listenStream = initial;
try
{
while (!token.IsCancellationRequested)
{
NamedPipeServerStream stream = listenStream!;
listenStream = null;
try
{
await stream.WaitForConnectionAsync(token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
stream.Dispose();
break;
}
catch (ObjectDisposedException)
{
break;
}
catch (IOException)
{
stream.Dispose();
break;
}
// .NET Framework 下 WaitForConnectionAsync 可能提前返回,此处校验连接确实建立
if (!stream.IsConnected)
{
try
{
await Task.Delay(50, token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
break;
}
listenStream = stream;
continue;
}
var client = new NamePipeClient(stream);
Task handler = Task.Run(() => HandleClientAsync(client, token));
RegisterClient(client, handler);
// 为下一个连接准备新的管道实例
try
{
listenStream = CreatePipeStream();
}
catch (Exception)
{
break;
}
lock (_sync)
{
if (!_running)
{
break;
}
_listenStream = listenStream;
}
}
}
catch (Exception)
{
// 监听循环中的未知异常直接结束循环,由 Stop 负责收尾
}
finally
{
try
{
listenStream?.Dispose();
}
catch
{
// 忽略关闭异常
}
lock (_sync)
{
_listenStream = null;
}
}
}
///
/// 单个连接的读取循环:按行读取消息并触发 。
///
private async Task HandleClientAsync(NamePipeClient client, CancellationToken token)
{
OnClientEvent(ClientConnected, client);
try
{
while (!token.IsCancellationRequested)
{
string? message = await client.ReadMessageAsync().ConfigureAwait(false);
if (message == null)
{
break;
}
RaiseDataReceived(client, message);
}
}
catch (OperationCanceledException)
{
// 服务停止导致的正常取消
}
catch (Exception)
{
// 连接断开、数据非法等情况直接结束该连接的读取
}
finally
{
OnClientEvent(ClientDisConnected, client);
UnregisterClient(client);
client.Dispose();
}
}
private void OnClientEvent(EventHandler? handler, IClient client)
{
if (handler == null)
{
return;
}
try
{
handler(this, client);
}
catch
{
// 订阅方的异常不应影响连接的建立与释放
}
}
private void RaiseDataReceived(NamePipeClient client, string raw)
{
var data = JsonSerializer.Deserialize(raw);
var arg = new RequestArg
{
Data = data,
Raw = raw,
Client = client
};
OnDataReceived(arg);
}
private void RegisterClient(NamePipeClient client, Task handler)
{
lock (_sync)
{
if (_running)
{
_clients[client] = handler;
return;
}
}
// 服务正在停止,直接释放该连接
client.Dispose();
}
private void UnregisterClient(NamePipeClient client)
{
lock (_sync)
{
_clients.Remove(client);
}
}
private void OnDataReceived(RequestArg arg)
{
EventHandler? handler = DataReceived;
if (handler == null)
{
return;
}
try
{
handler?.Invoke(this, arg);
}
catch
{
// 订阅方的异常不应中断管道读取
}
}
public void Dispose()
{
if (_disposed)
{
return;
}
try
{
Stop(out _);
}
catch
{
// 释放阶段的异常忽略
}
_disposed = true;
}
}
}