无网不进  
软硬件开发

文章系列目录

C#网络编程系列文章(一)之Socket实现异步TCP服务器 

C#网络编程系列文章(二)之Socket实现同步TCP服务器

C#网络编程系列文章(三)之TcpListener实现异步TCP服务器

C#网络编程系列文章(四)之TcpListener实现同步TCP服务器

C#网络编程系列文章(五)之Socket实现异步UDP服务器

C#网络编程系列文章(六)之Socket实现同步UDP服务器

C#网络编程系列文章(七)之UdpClient实现异步UDP服务器

C#网络编程系列文章(八)之UdpClient实现同步UDP服务器

参考路径:

https://blog.csdn.net/zhujunxxxxx/article/details/44258719

代码下载地址

http://download.csdn.net/detail/zhujunxxxxx/8510991

 

本文介绍
TcpListener 类提供一些简单方法,用于在阻止同步模式下侦听和接受传入连接请求。 可使用 TcpClient 或 Socket 来连接 TcpListener。 可使用 IPEndPoint、本地 IP 地址及端口号或者仅使用端口号,来创建 TcpListener。 可以将本地 IP 地址指定为 Any,将本地端口号指定为 0(如果希望基础服务提供程序为您分配这些值)。
 如果您选择这样做,可在连接套接字后使用 LocalEndpoint 属性来标识已指定的信息。使用 Start 方法,可开始侦听传入的连接请求。 Start 将对传入连接进行排队,直至您调用 Stop 方法或它已经完成 MaxConnections 排队为止。 可使用 AcceptSocket 或 AcceptTcpClient 从传入连接请求队列提取连接。 这两种方法将阻止。 如果要避免阻止,可首先使用 Pending 方法来确定队列中是否有可用的连接请求。
虽然TcpListener已经封装的比较不错了,我们于是就使用它在构造一个比较不错的异步TCP服务器,这里依然和前两章一样,给出服务器中的代码,代码中注释很详细,我也会给出相关的封装类。
TcpListener异步TCP服务器:

  1 using System;
  2 
  3 using System.Collections.Generic;
  4 
  5 using System.Linq;
  6 
  7 using System.Text;
  8 
  9 using System.Net.Sockets;
 10 
 11 using System.Net;
 12 
 13 namespace NetFrame.Net.TCP.Listener.Asynchronous
 14 
 15 {
 16 
 17     /// <summary>
 18 
 19     /// TcpListener实现异步TCP服务器
 20 
 21     /// </summary>
 22 
 23     public class AsyncTCPServer : IDisposable
 24 
 25     {
 26 
 27         #region Fields
 28 
 29         /// <summary>
 30 
 31         /// 服务器程序允许的最大客户端连接数
 32 
 33         /// </summary>
 34 
 35         private int _maxClient;
 36 
 37  
 38 
 39         /// <summary>
 40 
 41         /// 当前的连接的客户端数
 42 
 43         /// </summary>
 44 
 45         private int _clientCount;
 46 
 47  
 48 
 49         /// <summary>
 50 
 51         /// 服务器使用的异步TcpListener
 52 
 53         /// </summary>
 54 
 55         private TcpListener _listener;
 56 
 57  
 58 
 59         /// <summary>
 60 
 61         /// 客户端会话列表
 62 
 63         /// </summary>
 64 
 65         private List<Object> _clients;
 66 
 67  
 68 
 69         private bool disposed = false;
 70 
 71  
 72 
 73         #endregion
 74 
 75  
 76 
 77         #region Properties
 78 
 79  
 80 
 81         /// <summary>
 82 
 83         /// 服务器是否正在运行
 84 
 85         /// </summary>
 86 
 87         public bool IsRunning { get; private set; }
 88 
 89         /// <summary>
 90 
 91         /// 监听的IP地址
 92 
 93         /// </summary>
 94 
 95         public IPAddress Address { get; private set; }
 96 
 97         /// <summary>
 98 
 99         /// 监听的端口
100 
101         /// </summary>
102 
103         public int Port { get; private set; }
104 
105         /// <summary>
106 
107         /// 通信使用的编码
108 
109         /// </summary>
110 
111         public Encoding Encoding { get; set; }
112 
113  
114 
115  
116 
117         #endregion
118 
119  
120 
121         #region 构造函数
122 
123  
124 
125         /// <summary>
126 
127         /// 异步TCP服务器
128 
129         /// </summary>
130 
131         /// <param name="listenPort">监听的端口</param>
132 
133         public AsyncTCPServer(int listenPort)
134 
135             : this(IPAddress.Any, listenPort)
136 
137         {
138 
139         }
140 
141  
142 
143         /// <summary>
144 
145         /// 异步TCP服务器
146 
147         /// </summary>
148 
149         /// <param name="localEP">监听的终结点</param>
150 
151         public AsyncTCPServer(IPEndPoint localEP)
152 
153             : this(localEP.Address, localEP.Port)
154 
155         {
156 
157         }
158 
159  
160 
161         /// <summary>
162 
163         /// 异步TCP服务器
164 
165         /// </summary>
166 
167         /// <param name="localIPAddress">监听的IP地址</param>
168 
169         /// <param name="listenPort">监听的端口</param>
170 
171         public AsyncTCPServer(IPAddress localIPAddress, int listenPort)
172 
173         {
174 
175             Address = localIPAddress;
176 
177             Port = listenPort;
178 
179             this.Encoding = Encoding.Default;
180 
181  
182 
183             _clients = new List<Object>();
184 
185  
186 
187             _listener = new TcpListener(Address, Port);
188 
189             _listener.AllowNatTraversal(true);
190 
191         }
192 
193  
194 
195         #endregion
196 
197  
198 
199         #region Method
200 
201  
202 
203         /// <summary>
204 
205         /// 启动服务器
206 
207         /// </summary>
208 
209         public void Start()
210 
211         {
212 
213             if (!IsRunning)
214 
215             {
216 
217                 IsRunning = true;
218 
219                 _listener.Start();
220 
221                 _listener.BeginAcceptTcpClient(
222 
223                   new AsyncCallback(HandleTcpClientAccepted), _listener);
224 
225             }
226 
227         }
228 
229  
230 
231  
232 
233         /// <summary>
234 
235         /// 启动服务器
236 
237         /// </summary>
238 
239         /// <param name="backlog">
240 
241         /// 服务器所允许的挂起连接序列的最大长度
242 
243         /// </param>
244 
245         public void Start(int backlog)
246 
247         {
248 
249             if (!IsRunning)
250 
251             {
252 
253                 IsRunning = true;
254 
255                 _listener.Start(backlog);
256 
257                 _listener.BeginAcceptTcpClient(
258 
259                   new AsyncCallback(HandleTcpClientAccepted), _listener);
260 
261             }
262 
263         }
264 
265  
266 
267         /// <summary>
268 
269         /// 停止服务器
270 
271         /// </summary>
272 
273         public void Stop()
274 
275         {
276 
277             if (IsRunning)
278 
279             {
280 
281                 IsRunning = false;
282 
283                 _listener.Stop();
284 
285                 lock (_clients)
286 
287                 {
288 
289                     //关闭所有客户端连接
290 
291                     CloseAllClient();
292 
293                 }
294 
295             }
296 
297         }
298 
299  
300 
301         /// <summary>
302 
303         /// 处理客户端连接的函数
304 
305         /// </summary>
306 
307         /// <param name="ar"></param>
308 
309         private void HandleTcpClientAccepted(IAsyncResult ar)
310 
311         {
312 
313             if (IsRunning)
314 
315             {
316 
317                 //TcpListener tcpListener = (TcpListener)ar.AsyncState;
318 
319  
320 
321                 TcpClient client = _listener.EndAcceptTcpClient(ar);
322 
323                 byte[] buffer = new byte[client.ReceiveBufferSize];
324 
325  
326 
327                 TCPClientState state
328 
329                   = new TCPClientState(client, buffer);
330 
331                 lock (_clients)
332 
333                 {
334 
335                     _clients.Add(state);
336 
337                     RaiseClientConnected(state);
338 
339                 }
340 
341  
342 
343                 NetworkStream stream = state.NetworkStream;
344 
345                 //开始异步读取数据
346 
347                 stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
348 
349  
350 
351                 _listener.BeginAcceptTcpClient(
352 
353                   new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
354 
355             }
356 
357         }
358 
359         /// <summary>
360 
361         /// 数据接受回调函数
362 
363         /// </summary>
364 
365         /// <param name="ar"></param>
366 
367         private void HandleDataReceived(IAsyncResult ar)
368 
369         {
370 
371             if (IsRunning)
372 
373             {
374 
375                 TCPClientState state = (TCPClientState)ar.AsyncState;
376 
377                 NetworkStream stream = state.NetworkStream;
378 
379  
380 
381                 int recv = 0;
382 
383                 try
384 
385                 {
386 
387                     recv = stream.EndRead(ar);
388 
389                 }
390 
391                 catch
392 
393                 {
394 
395                     recv = 0;
396 
397                 }
398 
399  
400 
401                 if (recv == 0)
402 
403                 {
404 
405                     // connection has been closed
406 
407                     lock (_clients)
408 
409                     {
410 
411                         _clients.Remove(state);
412 
413                         //触发客户端连接断开事件
414 
415                         RaiseClientDisconnected(state);
416 
417                         return;
418 
419                     }
420 
421                 }
422 
423  
424 
425                 // received byte and trigger event notification
426 
427                 byte[] buff = new byte[recv];
428 
429                 Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);
430 
431                 //触发数据收到事件
432 
433                 RaiseDataReceived(state);
434 
435  
436 
437                 // continue listening for tcp datagram packets
438 
439                 stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
440 
441             }
442 
443         }
444 
445  
446 
447         /// <summary>
448 
449         /// 发送数据
450 
451         /// </summary>
452 
453         /// <param name="state">接收数据的客户端会话</param>
454 
455         /// <param name="data">数据报文</param>
456 
457         public void Send(TCPClientState state, byte[] data)
458 
459         {
460 
461             RaisePrepareSend(state);
462 
463             Send(state.TcpClient, data);
464 
465         }
466 
467  
468 
469         /// <summary>
470 
471         /// 异步发送数据至指定的客户端
472 
473         /// </summary>
474 
475         /// <param name="client">客户端</param>
476 
477         /// <param name="data">报文</param>
478 
479         public void Send(TcpClient client, byte[] data)
480 
481         {
482 
483             if (!IsRunning)
484 
485                 throw new InvalidProgramException("This TCP Scoket server has not been started.");
486 
487  
488 
489             if (client == null)
490 
491                 throw new ArgumentNullException("client");
492 
493  
494 
495             if (data == null)
496 
497                 throw new ArgumentNullException("data");
498 
499             client.GetStream().BeginWrite(data, 0, data.Length, SendDataEnd, client);
500 
501         }
502 
503  
504 
505         /// <summary>
506 
507         /// 发送数据完成处理函数
508 
509         /// </summary>
510 
511         /// <param name="ar">目标客户端Socket</param>
512 
513         private void SendDataEnd(IAsyncResult ar)
514 
515         {
516 
517             ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
518 
519             RaiseCompletedSend(null);
520 
521         }
522 
523         #endregion
524 
525  
526 
527         #region 事件
528 
529  
530 
531         /// <summary>
532 
533         /// 与客户端的连接已建立事件
534 
535         /// </summary>
536 
537         public event EventHandler<AsyncEventArgs> ClientConnected;
538 
539         /// <summary>
540 
541         /// 与客户端的连接已断开事件
542 
543         /// </summary>
544 
545         public event EventHandler<AsyncEventArgs> ClientDisconnected;
546 
547  
548 
549  
550 
551         /// <summary>
552 
553         /// 触发客户端连接事件
554 
555         /// </summary>
556 
557         /// <param name="state"></param>
558 
559         private void RaiseClientConnected(TCPClientState state)
560 
561         {
562 
563             if (ClientConnected != null)
564 
565             {
566 
567                 ClientConnected(this, new AsyncEventArgs(state));
568 
569             }
570 
571         }
572 
573         /// <summary>
574 
575         /// 触发客户端连接断开事件
576 
577         /// </summary>
578 
579         /// <param name="client"></param>
580 
581         private void RaiseClientDisconnected(TCPClientState state)
582 
583         {
584 
585             if (ClientDisconnected != null)
586 
587             {
588 
589                 ClientDisconnected(this, new AsyncEventArgs("连接断开"));
590 
591             }
592 
593         }
594 
595  
596 
597         /// <summary>
598 
599         /// 接收到数据事件
600 
601         /// </summary>
602 
603         public event EventHandler<AsyncEventArgs> DataReceived;
604 
605  
606 
607         private void RaiseDataReceived(TCPClientState state)
608 
609         {
610 
611             if (DataReceived != null)
612 
613             {
614 
615                 DataReceived(this, new AsyncEventArgs(state));
616 
617             }
618 
619         }
620 
621  
622 
623         /// <summary>
624 
625         /// 发送数据前的事件
626 
627         /// </summary>
628 
629         public event EventHandler<AsyncEventArgs> PrepareSend;
630 
631  
632 
633         /// <summary>
634 
635         /// 触发发送数据前的事件
636 
637         /// </summary>
638 
639         /// <param name="state"></param>
640 
641         private void RaisePrepareSend(TCPClientState state)
642 
643         {
644 
645             if (PrepareSend != null)
646 
647             {
648 
649                 PrepareSend(this, new AsyncEventArgs(state));
650 
651             }
652 
653         }
654 
655  
656 
657         /// <summary>
658 
659         /// 数据发送完毕事件
660 
661         /// </summary>
662 
663         public event EventHandler<AsyncEventArgs> CompletedSend;
664 
665  
666 
667         /// <summary>
668 
669         /// 触发数据发送完毕的事件
670 
671         /// </summary>
672 
673         /// <param name="state"></param>
674 
675         private void RaiseCompletedSend(TCPClientState state)
676 
677         {
678 
679             if (CompletedSend != null)
680 
681             {
682 
683                 CompletedSend(this, new AsyncEventArgs(state));
684 
685             }
686 
687         }
688 
689  
690 
691         /// <summary>
692 
693         /// 网络错误事件
694 
695         /// </summary>
696 
697         public event EventHandler<AsyncEventArgs> NetError;
698 
699         /// <summary>
700 
701         /// 触发网络错误事件
702 
703         /// </summary>
704 
705         /// <param name="state"></param>
706 
707         private void RaiseNetError(TCPClientState state)
708 
709         {
710 
711             if (NetError != null)
712 
713             {
714 
715                 NetError(this, new AsyncEventArgs(state));
716 
717             }
718 
719         }
720 
721  
722 
723         /// <summary>
724 
725         /// 异常事件
726 
727         /// </summary>
728 
729         public event EventHandler<AsyncEventArgs> OtherException;
730 
731         /// <summary>
732 
733         /// 触发异常事件
734 
735         /// </summary>
736 
737         /// <param name="state"></param>
738 
739         private void RaiseOtherException(TCPClientState state, string descrip)
740 
741         {
742 
743             if (OtherException != null)
744 
745             {
746 
747                 OtherException(this, new AsyncEventArgs(descrip, state));
748 
749             }
750 
751         }
752 
753         private void RaiseOtherException(TCPClientState state)
754 
755         {
756 
757             RaiseOtherException(state, "");
758 
759         }
760 
761  
762 
763         #endregion
764 
765  
766 
767         #region Close
768 
769         /// <summary>
770 
771         /// 关闭一个与客户端之间的会话
772 
773         /// </summary>
774 
775         /// <param name="state">需要关闭的客户端会话对象</param>
776 
777         public void Close(TCPClientState state)
778 
779         {
780 
781             if (state != null)
782 
783             {
784 
785                 state.Close();
786 
787                 _clients.Remove(state);
788 
789                 _clientCount--;
790 
791                 //TODO 触发关闭事件
792 
793             }
794 
795         }
796 
797         /// <summary>
798 
799         /// 关闭所有的客户端会话,与所有的客户端连接会断开
800 
801         /// </summary>
802 
803         public void CloseAllClient()
804 
805         {
806 
807             foreach (TCPClientState client in _clients)
808 
809             {
810 
811                 Close(client);
812 
813             }
814 
815             _clientCount = 0;
816 
817             _clients.Clear();
818 
819         }
820 
821         #endregion
822 
823  
824 
825         #region 释放
826 
827         /// <summary>
828 
829         /// Performs application-defined tasks associated with freeing, 
830 
831         /// releasing, or resetting unmanaged resources.
832 
833         /// </summary>
834 
835         public void Dispose()
836 
837         {
838 
839             Dispose(true);
840 
841             GC.SuppressFinalize(this);
842 
843         }
844 
845  
846 
847         /// <summary>
848 
849         /// Releases unmanaged and - optionally - managed resources
850 
851         /// </summary>
852 
853         /// <param name="disposing"><c>true</c> to release 
854 
855         /// both managed and unmanaged resources; <c>false</c> 
856 
857         /// to release only unmanaged resources.</param>
858 
859         protected virtual void Dispose(bool disposing)
860 
861         {
862 
863             if (!this.disposed)
864 
865             {
866 
867                 if (disposing)
868 
869                 {
870 
871                     try
872 
873                     {
874 
875                         Stop();
876 
877                         if (_listener != null)
878 
879                         {
880 
881                             _listener = null;
882 
883                         }
884 
885                     }
886 
887                     catch (SocketException)
888 
889                     {
890 
891                         //TODO
892 
893                         RaiseOtherException(null);
894 
895                     }
896 
897                 }
898 
899                 disposed = true;
900 
901             }
902 
903         }
904 
905         #endregion
906 
907     }
908 
909 }

客户端处理封装类:

 1 using System;
 2 
 3 using System.Collections.Generic;
 4 
 5 using System.Linq;
 6 
 7 using System.Text;
 8 
 9 using System.Net.Sockets;
10 
11  
12 
13 namespace NetFrame.Net.TCP.Listener.Asynchronous
14 
15 {
16 
17     public class TCPClientState
18 
19     {
20 
21         /// <summary>
22 
23         /// 与客户端相关的TcpClient
24 
25         /// </summary>
26 
27         public TcpClient TcpClient { get; private set; }
28 
29  
30 
31         /// <summary>
32 
33         /// 获取缓冲区
34 
35         /// </summary>
36 
37         public byte[] Buffer { get; private set; }
38 
39  
40 
41         /// <summary>
42 
43         /// 获取网络流
44 
45         /// </summary>
46 
47         public NetworkStream NetworkStream
48 
49         {
50 
51             get { return TcpClient.GetStream(); }
52 
53         }
54 
55  
56 
57         public TCPClientState(TcpClient tcpClient, byte[] buffer)
58 
59         {
60 
61             if (tcpClient == null)
62 
63                 throw new ArgumentNullException("tcpClient");
64 
65             if (buffer == null)
66 
67                 throw new ArgumentNullException("buffer");
68 
69  
70 
71             this.TcpClient = tcpClient;
72 
73             this.Buffer = buffer;
74 
75         }
76 
77         /// <summary>
78 
79         /// 关闭
80 
81         /// </summary>
82 
83         public void Close()
84 
85         {
86 
87             //关闭数据的接受和发送
88 
89             TcpClient.Close();
90 
91             Buffer = null;
92 
93         }
94 
95     }
96 
97 }

服务器事件参数类:

 1 using System;
 2 
 3 using System.Collections.Generic;
 4 
 5 using System.Linq;
 6 
 7 using System.Text;
 8 
 9  
10 
11 namespace NetFrame.Net.TCP.Listener.Asynchronous
12 
13 {
14 
15     /// <summary>
16 
17     /// 异步TcpListener TCP服务器事件参数类 
18 
19     /// </summary>
20 
21     public class AsyncEventArgs:EventArgs
22 
23     {
24 
25          /// <summary>
26 
27         /// 提示信息
28 
29         /// </summary>
30 
31         public string _msg;
32 
33  
34 
35         /// <summary>
36 
37         /// 客户端状态封装类
38 
39         /// </summary>
40 
41         public TCPClientState _state;
42 
43  
44 
45         /// <summary>
46 
47         /// 是否已经处理过了
48 
49         /// </summary>
50 
51         public bool IsHandled { get; set; }
52 
53  
54 
55         public AsyncEventArgs(string msg)
56 
57         {
58 
59             this._msg = msg;
60 
61             IsHandled = false;
62 
63         }
64 
65         public AsyncEventArgs(TCPClientState state)
66 
67         {
68 
69             this._state = state;
70 
71             IsHandled = false;
72 
73         }
74 
75         public AsyncEventArgs(string msg, TCPClientState state)
76 
77         {
78 
79             this._msg = msg;
80 
81             this._state = state;
82 
83             IsHandled = false;
84 
85         }
86 
87     }
88 
89 }

 

posted on 2019-01-23 11:35  无网不进  阅读(1811)  评论(0)    收藏  举报