Shuxia Ning
2024-10-08 cf4967a0aebab18c5a37137f3e4c61b2d73a54bb
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
 
namespace IStation
{
    /// <summary>
    /// TcpListener实现异步TCP服务器
    /// </summary>
    public class AsyncTcpServer: IDisposable 
    {
        #region 私有字段
 
        private readonly object _obj = new object();//lock对象
        private TcpListener _listener;//服务器使用的异步TcpListener
        private  List<TcpClientState> _tcpClientStates;//客户端会话列表
        private bool _disposed = false;//是否已经释放
 
        #endregion
 
        #region 属性
 
        /// <summary>
        /// 服务器是否正在运行
        /// </summary>
        public bool IsRunning { get; private set; }
 
        /// <summary>
        /// 监听的IP地址
        /// </summary>
        public IPAddress Address { get; private set; }
 
        /// <summary>
        /// 监听的端口
        /// </summary>
        public int Port { get; private set; }
 
        #endregion
 
        #region 构造函数
 
        /// <summary>
        /// 异步TCP服务器
        /// </summary>
        /// <param name="LocalServerIPAddress">监听的IP地址</param>
        /// <param name="listenPort">监听的端口</param>
        public AsyncTcpServer(IPAddress ipAddress, int port)
        {
            this.Address = ipAddress;
            this.Port = port;
 
            _tcpClientStates = new List<TcpClientState>();
            _listener = new TcpListener(Address, Port);
            _listener.AllowNatTraversal(true);
        }
 
        #endregion
 
        #region Method
 
        /// <summary>
        /// 启动服务器
        /// </summary>
        public void Start()
        {
            if (!this.IsRunning)
            {
                this.IsRunning = true;
                _listener.Start();
                _listener.BeginAcceptTcpClient(
                  new AsyncCallback(HandleTcpClientAccepted), _listener);
            }
        }
 
        /// <summary>
        /// 启动服务器
        /// </summary>
        /// <param name="backlog">
        /// 服务器所允许的挂起连接序列的最大长度
        /// </param>
        public void Start(int backlog)
        {
            if (!this.IsRunning)
            {
                this.IsRunning = true;
                _listener.Start(backlog);
                _listener.BeginAcceptTcpClient(
                  new AsyncCallback(HandleTcpClientAccepted), _listener);
            }
        }
 
        /// <summary>
        /// 停止服务器
        /// </summary>
        public void Stop()
        {
            if (IsRunning)
            {
                IsRunning = false;
                _listener.Stop();
                lock (_obj)
                {
                    //关闭所有客户端连接
                    _tcpClientStates.ForEach(x=>x.Close());
                    _tcpClientStates.Clear();
                }
            }
        }
 
        /// <summary>
        /// 处理客户端连接的函数
        /// </summary>
        /// <param name="ar"></param>
        private void HandleTcpClientAccepted(IAsyncResult ar)
        {
            if (IsRunning)
            {
                //TcpListener tcpListener = (TcpListener)ar.AsyncState;
                var client = _listener.EndAcceptTcpClient(ar);
                var buffer = new byte[client.ReceiveBufferSize];
 
                var state = new TcpClientState(client,buffer);
                lock (_obj)
                {
                    _tcpClientStates.Add(state);
                    RaiseClientConnected(state);
                }
 
                NetworkStream stream = state.NetworkStream;
                //开始异步读取数据
                stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
 
                _listener.BeginAcceptTcpClient(
                  new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
            }
        }
 
        /// <summary>
        /// 数据接收回调函数
        /// </summary>
        /// <param name="ar"></param>
        private void HandleDataReceived(IAsyncResult ar)
        {
            if (IsRunning)
            {
                var state = (TcpClientState)ar.AsyncState;
                var stream = state.NetworkStream;
 
                int recv = 0;
                try
                {
                    recv = stream.EndRead(ar);
                }
                catch
                {
                    recv = 0;
                }
 
                if (recv == 0)
                {
                    // connection has been closed
                    lock (_obj)
                    {
                        _tcpClientStates.Remove(state);
                        //触发客户端连接断开事件
                        RaiseClientDisconnected(state);
                        return;
                    }
                }
 
                // received byte and trigger event notification
                byte[] buff = new byte[recv];
                Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);
 
                //触发数据收到事件
                RaiseDataReceived(state,buff);
 
                // continue listening for tcp datagram packets
                stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
            }
        }
 
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="state">接收数据的客户端会话</param>
        /// <param name="data">数据报文</param>
        public void Send(TcpClientState state, byte[] data)
        {
            if (!IsRunning)
                return;
            state.NetworkStream.BeginWrite(data, 0, data.Length, SendDataEnd, state.TcpClient);
        }
 
        /// <summary>
        /// 发送数据完成处理函数
        /// </summary>
        /// <param name="ar">目标客户端Socket</param>
        private void SendDataEnd(IAsyncResult ar)
        {
            ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
        }
 
        #endregion
 
        #region 事件
 
        /// <summary>
        /// 与客户端的连接已建立事件
        /// </summary>
        public event EventHandler<AsyncTcpEventArgs> TcpClientConnected;
 
        /// <summary>
        /// 与客户端的连接已断开事件
        /// </summary>
        public event EventHandler<AsyncTcpEventArgs> TcpClientDisconnected;
 
        /// <summary>
        /// 接收到数据事件
        /// </summary>
        public event Action<TcpClientState, byte[]> DataReceived;
 
        /// <summary>
        /// 触发客户端连接事件
        /// </summary>
        /// <param name="state"></param>
        private void RaiseClientConnected(TcpClientState state)
        {
            if(this.TcpClientConnected!=null)
                this.TcpClientConnected(this, new AsyncTcpEventArgs(state));
        }
 
        /// <summary>
        /// 触发客户端连接断开事件
        /// </summary>
        /// <param name="client"></param>
        private void RaiseClientDisconnected(TcpClientState state)
        {
            if(this.TcpClientDisconnected!=null)
                this.TcpClientDisconnected(this, new AsyncTcpEventArgs(state));
        }
 
        /// <summary>
        /// 触发接收到数据报文事件
        /// </summary>
        /// <param name="state"></param>
        private void RaiseDataReceived(TcpClientState state,byte[] bytes)
        {
            if(this.DataReceived!=null)
                this.DataReceived(state,bytes);
        }
 
 
        #endregion
 
        #region 释放
 
        /// <summary>
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release 
        /// both managed and unmanaged resources; <c>false</c> 
        /// to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (disposing)
                {
                    try
                    {
                        Stop();
                        if (_listener != null)
                        {
                            _listener = null;
                        }
                    }
                    catch //(SocketException ex)
                    {
                        //TODO
                        //throw ex;
                    }
                }
                _disposed = true;
            }
        }
 
        #endregion
 
 
 
    }
 
 
 
}