alielie
2025-11-25 006c98e5650b530e5220f279c1e803fefe69d40d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
using System;
using System.Collections.Concurrent;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConnectionUtil
{
    public static class PipeStreamUtil
    {
        public static string ReadMessage(this PipeStream ps)
        {
 
            MemoryStream ms = new MemoryStream();
            byte[] buffer = new byte[0x1000];
            do
            {
                ms.Write(buffer, 0, ps.Read(buffer, 0, buffer.Length));
            }
            while (!ps.IsMessageComplete);
            return Encoding.UTF8.GetString(ms.ToArray());
        }
 
        public static void WriteMessage(this PipeStream ps, string message)
        {
            var msg = Encoding.UTF8.GetBytes(message);
            ps.Write(msg, 0, msg.Length);
            ps.Flush();
        }
    }
 
    public class PipeServer2 : IDisposable
    {
        private readonly string _pipeName;
        private readonly int _maxNumberOfServerInstances;
        private readonly CancellationTokenSource _cancellationTokenSource;
        private readonly ConcurrentDictionary<string, NamedPipeServerStream> _activeConnections;
        private readonly ReaderWriterLockSlim _lock;
        private bool _isDisposed;
        private bool _isRunning;
 
        // 事件定义
        public event EventHandler<PipeDataEventArgs> OnData;
        public event EventHandler<PipeConnectionEventArgs> OnClientConnected;
        public event EventHandler<PipeConnectionEventArgs> OnClientDisconnected;
        public event EventHandler<PipeErrorEventArgs> OnError;
 
        public PipeServer2(string pipeName, int maxNumberOfServerInstances = 254)
        {
            _pipeName = pipeName;
            _maxNumberOfServerInstances = maxNumberOfServerInstances;
            _cancellationTokenSource = new CancellationTokenSource();
            _activeConnections = new ConcurrentDictionary<string, NamedPipeServerStream>();
            _lock = new ReaderWriterLockSlim();
        }
 
        public void Start()
        {
            if (_isRunning)
                return;
 
            _isRunning = true;
 
            Task.Run(() =>
            {
                while (_isRunning && !_cancellationTokenSource.Token.IsCancellationRequested)
                {
                    try
                    {
                        var pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, _maxNumberOfServerInstances
                            , PipeTransmissionMode.Message);
                        pipeServer.WaitForConnection();
 
                        string clientId = Guid.NewGuid().ToString();
                        if (_activeConnections.TryAdd(clientId, pipeServer))
                        {
                            // 启动处理客户端消息的线程
                            Thread clientThread = new Thread(() => HandleClient(clientId, pipeServer));
                            clientThread.Start();
 
                            OnClientConnected?.Invoke(this, new PipeConnectionEventArgs(clientId));
                        }
                    }
                    catch (Exception ex)
                    {
                        OnError?.Invoke(this, new PipeErrorEventArgs("Connect", ex));
                        Thread.Sleep(1000); // 发生错误时等待一秒再重试
                    }
                }
            });
        }
 
 
 
        private void HandleClient(string clientId, NamedPipeServerStream pipeServer)
        {
            try
            {
                while (!_cancellationTokenSource.Token.IsCancellationRequested)
                {
                    try
                    {
                        // 等待客户端发送消息
                        string message = pipeServer.ReadMessage();
                        if (string.IsNullOrEmpty(message))
                            break;
 
                        OnData?.Invoke(this, new PipeDataEventArgs(clientId, message));
                    }
                    catch (Exception ex)
                    {
                        OnError?.Invoke(this, new PipeErrorEventArgs("HandleClientMessageError", ex));
                        break;
                    }
                }
            }
            finally
            {
                if (_activeConnections.TryRemove(clientId, out var pipe))
                {
                    pipe.Dispose();
                }
                OnClientDisconnected?.Invoke(this, new PipeConnectionEventArgs(clientId));
            }
        }
 
        public void SendMessage(string clientId, string message)
        {
            if (!_activeConnections.TryGetValue(clientId, out var pipeServer))
            {
                throw new InvalidOperationException($"找不到客户端 {clientId}");
            }
 
            _lock.EnterWriteLock();
            try
            {
                try
                {
                    pipeServer.WriteMessage(message);
                }
                catch (Exception ex)
                {
                    OnError?.Invoke(this, new PipeErrorEventArgs($"向客户端 {clientId} 发送消息时发生错误", ex));
                }
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
 
        public void BroadcastMessage(string message)
        {
            _lock.EnterWriteLock();
            try
            {
                foreach (var pipeServer in _activeConnections.Values)
                {
                    pipeServer.WriteMessage(message);
                }
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
 
        public void Stop()
        {
            _isRunning = false;
            _cancellationTokenSource.Cancel();
        }
 
        public void Dispose()
        {
            if (!_isDisposed)
            {
                Stop();
                foreach (var pipeServer in _activeConnections.Values)
                {
                    pipeServer.Dispose();
                }
                _activeConnections.Clear();
                _cancellationTokenSource.Dispose();
                _lock.Dispose();
                _isDisposed = true;
            }
        }
    }
}