无网不进  
软硬件开发

文章系列目录

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

本文介绍
在上一篇博客中我说了,我将会介绍c#中使用Socket和TcpListener和UdpClient实现各种同步和异步的TCP和UDP服务器,这些都是是我自己花了很多天的时间来总结的,这样一来相信刚接触c#网络编程的朋友们不会像以前的我一样到处出找资料,到处调试。本次我介绍的是使用Socket来实现的同步的TCP服务器,同步的TCP服务器和第一篇里面介绍的异步TCP服务器的区别就是,在Socket调用Accept的时候是否会阻塞。
同步的TCP服务器在接受到一个客户端的请求的时候一般是开启一个线程去处理和这个客户端的通信工作,这种方式的不好的地方就是资源消耗大,但是假如使用线程池的话,事先分配一定数量的线程,性能还是可以。
但是我之所以给出很多方法实现的服务器,主要目的就是想测试哪种情况性能比较不错,就目前来看,异步的模式比较NICE,但是其实还有一种IOCP模式性能是最好的。。。
Socket同步TCP服务器
---------------------
作者:小竹zz
来源:CSDN
原文:https://blog.csdn.net/zhujunxxxxx/article/details/44261375
版权声明:本文为博主原创文章,转载请附上博文链接!

服务端代码:

  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 using System.Threading;
 14 
 15  
 16 
 17 namespace NetFrame.Net.TCP.Sock.Synchronous
 18 
 19 {
 20 
 21     /// <summary>
 22 
 23     /// 基于socket实现的同步TCP服务器
 24 
 25     /// </summary>
 26 
 27     public class SocketTCPServer
 28 
 29     {
 30 
 31         #region Fields
 32 
 33         /// <summary>
 34 
 35         /// 服务器程序允许的最大客户端连接数
 36 
 37         /// </summary>
 38 
 39         private int _maxClient;
 40 
 41  
 42 
 43         /// <summary>
 44 
 45         /// 当前的连接的客户端数
 46 
 47         /// </summary>
 48 
 49         private int _clientCount;
 50 
 51  
 52 
 53         /// <summary>
 54 
 55         /// 服务器使用的异步socket
 56 
 57         /// </summary>
 58 
 59         private Socket _serverSock;
 60 
 61  
 62 
 63         /// <summary>
 64 
 65         /// 客户端会话列表
 66 
 67         /// </summary>
 68 
 69         private List<SocketClientHandle> _clients;
 70 
 71  
 72 
 73         private bool disposed = false;
 74 
 75  
 76 
 77         #endregion
 78 
 79  
 80 
 81         #region Properties
 82 
 83  
 84 
 85         /// <summary>
 86 
 87         /// 服务器是否正在运行
 88 
 89         /// </summary>
 90 
 91         public bool IsRunning { get; private set; }
 92 
 93         /// <summary>
 94 
 95         /// 监听的IP地址
 96 
 97         /// </summary>
 98 
 99         public IPAddress Address { get; private set; }
100 
101         /// <summary>
102 
103         /// 监听的端口
104 
105         /// </summary>
106 
107         public int Port { get; private set; }
108 
109         /// <summary>
110 
111         /// 通信使用的编码
112 
113         /// </summary>
114 
115         public Encoding Encoding { get; set; }
116 
117  
118 
119  
120 
121         #endregion
122 
123  
124 
125         #region 构造函数
126 
127         /// <summary>
128 
129         /// 同步Socket TCP服务器
130 
131         /// </summary>
132 
133         /// <param name="listenPort">监听的端口</param>
134 
135         public SocketTCPServer(int listenPort)
136 
137             : this(IPAddress.Any, listenPort, 1024)
138 
139         {
140 
141         }
142 
143  
144 
145         /// <summary>
146 
147         /// 同步Socket TCP服务器
148 
149         /// </summary>
150 
151         /// <param name="localEP">监听的终结点</param>
152 
153         public SocketTCPServer(IPEndPoint localEP)
154 
155             : this(localEP.Address, localEP.Port, 1024)
156 
157         {
158 
159         }
160 
161  
162 
163         /// <summary>
164 
165         /// 同步Socket TCP服务器
166 
167         /// </summary>
168 
169         /// <param name="localIPAddress">监听的IP地址</param>
170 
171         /// <param name="listenPort">监听的端口</param>
172 
173         /// <param name="maxClient">最大客户端数量</param>
174 
175         public SocketTCPServer(IPAddress localIPAddress, int listenPort, int maxClient)
176 
177         {
178 
179             this.Address = localIPAddress;
180 
181             this.Port = listenPort;
182 
183             this.Encoding = Encoding.Default;
184 
185  
186 
187             _maxClient = maxClient;
188 
189             _clients = new List<SocketClientHandle>();
190 
191             _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
192 
193         }
194 
195  
196 
197         #endregion
198 
199  
200 
201         #region Method
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                 _serverSock.Bind(new IPEndPoint(this.Address, this.Port));
220 
221                 Thread thread = new Thread(StartListen);
222 
223                 thread.Start();
224 
225  
226 
227             }
228 
229         }
230 
231         /// <summary>
232 
233         /// 开始进行监听
234 
235         /// </summary>
236 
237         private void StartListen()
238 
239         {
240 
241             _serverSock.Listen(1024);
242 
243             SocketClientHandle handle;
244 
245             while (IsRunning)
246 
247             {
248 
249                 if (_clientCount >= _maxClient)
250 
251                 {
252 
253                     //TODO 客户端过多异常
254 
255                     RaiseOtherException(null);
256 
257                 }
258 
259                 else
260 
261                 {
262 
263                     Socket clientSock = _serverSock.Accept();
264 
265                     _clientCount++;
266 
267                     //TODO 创建一个处理客户端的线程并启动
268 
269                     handle = new SocketClientHandle(clientSock);
270 
271                     _clients.Add(handle);
272 
273                     //使用线程池来操作
274 
275                     ThreadPool.QueueUserWorkItem(new WaitCallback(handle.RecevieData));
276 
277  
278 
279                     //Thread pthread;
280 
281                     //pthread = new Thread(new ThreadStart(client.RecevieData));
282 
283                     //pthread.Start();
284 
285                     //这里应该使用线程池来进行
286 
287                 }
288 
289             }
290 
291  
292 
293         }
294 
295         /// <summary>
296 
297         /// 停止服务器
298 
299         /// </summary>
300 
301         public void Stop()
302 
303         {
304 
305             if (IsRunning)
306 
307             {
308 
309                 IsRunning = false;
310 
311                 _serverSock.Close();
312 
313                 //TODO 关闭对所有客户端的连接
314 
315  
316 
317             }
318 
319         }
320 
321         /// <summary>
322 
323         /// 发送函数
324 
325         /// </summary>
326 
327         public void Send(string msg, SocketClientHandle client)
328 
329         {
330 
331             //TODO
332 
333         }
334 
335  
336 
337         /// <summary>
338 
339         /// 关闭一个与客户端之间的会话
340 
341         /// </summary>
342 
343         /// <param name="handle">需要关闭的客户端会话对象</param>
344 
345         public void Close(SocketClientHandle handle)
346 
347         {
348 
349             if (handle != null)
350 
351             {
352 
353                 _clients.Remove(handle);
354 
355                 handle.Dispose();
356 
357                 _clientCount--;
358 
359                 //TODO 触发关闭事件
360 
361                 
362 
363             }
364 
365         }
366 
367         /// <summary>
368 
369         /// 关闭所有的客户端会话,与所有的客户端连接会断开
370 
371         /// </summary>
372 
373         public void CloseAllClient()
374 
375         {
376 
377             foreach (SocketClientHandle handle in _clients)
378 
379             {
380 
381                 Close(handle);
382 
383             }
384 
385             _clientCount = 0;
386 
387             _clients.Clear();
388 
389         }
390 
391  
392 
393         #endregion
394 
395  
396 
397         #region 事件
398 
399  
400 
401         /// <summary>
402 
403         /// 与客户端的连接已建立事件
404 
405         /// </summary>
406 
407         public event EventHandler<SocketEventArgs> ClientConnected;
408 
409         /// <summary>
410 
411         /// 与客户端的连接已断开事件
412 
413         /// </summary>
414 
415         public event EventHandler<SocketEventArgs> ClientDisconnected;
416 
417  
418 
419         /// <summary>
420 
421         /// 触发客户端连接事件
422 
423         /// </summary>
424 
425         /// <param name="state"></param>
426 
427         private void RaiseClientConnected(SocketClientHandle handle)
428 
429         {
430 
431             if (ClientConnected != null)
432 
433             {
434 
435                 ClientConnected(this, new SocketEventArgs(handle));
436 
437             }
438 
439         }
440 
441         /// <summary>
442 
443         /// 触发客户端连接断开事件
444 
445         /// </summary>
446 
447         /// <param name="client"></param>
448 
449         private void RaiseClientDisconnected(Socket client)
450 
451         {
452 
453             if (ClientDisconnected != null)
454 
455             {
456 
457                 ClientDisconnected(this, new SocketEventArgs("连接断开"));
458 
459             }
460 
461         }
462 
463  
464 
465         /// <summary>
466 
467         /// 接收到数据事件
468 
469         /// </summary>
470 
471         public event EventHandler<SocketEventArgs> DataReceived;
472 
473  
474 
475         private void RaiseDataReceived(SocketClientHandle handle)
476 
477         {
478 
479             if (DataReceived != null)
480 
481             {
482 
483                 DataReceived(this, new SocketEventArgs(handle));
484 
485             }
486 
487         }
488 
489  
490 
491         /// <summary>
492 
493         /// 数据发送事件
494 
495         /// </summary>
496 
497         public event EventHandler<SocketEventArgs> CompletedSend;
498 
499  
500 
501         /// <summary>
502 
503         /// 触发数据发送事件
504 
505         /// </summary>
506 
507         /// <param name="state"></param>
508 
509         private void RaiseCompletedSend(SocketClientHandle handle)
510 
511         {
512 
513             if (CompletedSend != null)
514 
515             {
516 
517                 CompletedSend(this, new SocketEventArgs(handle));
518 
519             }
520 
521         }
522 
523  
524 
525  
526 
527         /// <summary>
528 
529         /// 网络错误事件
530 
531         /// </summary>
532 
533         public event EventHandler<SocketEventArgs> NetError;
534 
535         /// <summary>
536 
537         /// 触发网络错误事件
538 
539         /// </summary>
540 
541         /// <param name="state"></param>
542 
543         private void RaiseNetError(SocketClientHandle handle)
544 
545         {
546 
547             if (NetError != null)
548 
549             {
550 
551                 NetError(this, new SocketEventArgs(handle));
552 
553             }
554 
555         }
556 
557  
558 
559         /// <summary>
560 
561         /// 异常事件
562 
563         /// </summary>
564 
565         public event EventHandler<SocketEventArgs> OtherException;
566 
567         /// <summary>
568 
569         /// 触发异常事件
570 
571         /// </summary>
572 
573         /// <param name="state"></param>
574 
575         private void RaiseOtherException(SocketClientHandle handle, string descrip)
576 
577         {
578 
579             if (OtherException != null)
580 
581             {
582 
583                 OtherException(this, new SocketEventArgs(descrip, handle));
584 
585             }
586 
587         }
588 
589         private void RaiseOtherException(SocketClientHandle handle)
590 
591         {
592 
593             RaiseOtherException(handle, "");
594 
595         }
596 
597  
598 
599         #endregion
600 
601  
602 
603         #region Close 未实现
604 
605         #endregion
606 
607  
608 
609         #region 释放
610 
611         /// <summary>
612 
613         /// Performs application-defined tasks associated with freeing, 
614 
615         /// releasing, or resetting unmanaged resources.
616 
617         /// </summary>
618 
619         public void Dispose()
620 
621         {
622 
623             Dispose(true);
624 
625             GC.SuppressFinalize(this);
626 
627         }
628 
629  
630 
631         /// <summary>
632 
633         /// Releases unmanaged and - optionally - managed resources
634 
635         /// </summary>
636 
637         /// <param name="disposing"><c>true</c> to release 
638 
639         /// both managed and unmanaged resources; <c>false</c> 
640 
641         /// to release only unmanaged resources.</param>
642 
643         protected virtual void Dispose(bool disposing)
644 
645         {
646 
647             if (!this.disposed)
648 
649             {
650 
651                 if (disposing)
652 
653                 {
654 
655                     try
656 
657                     {
658 
659                         Stop();
660 
661                         if (_serverSock != null)
662 
663                         {
664 
665                             _serverSock = null;
666 
667                         }
668 
669                     }
670 
671                     catch (SocketException)
672 
673                     {
674 
675                         //TODO 异常
676 
677                     }
678 
679                 }
680 
681                 disposed = true;
682 
683             }
684 
685         }
686 
687         #endregion
688 
689     }
690 
691 }

 

对客户端操作封装的Handle类:

  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.Sock.Synchronous
 14 
 15 {
 16 
 17     /// <summary>
 18 
 19     /// Socket 服务器用于处理客户端连接封装的客户端处理类
 20 
 21     /// </summary>
 22 
 23     public class SocketClientHandle:IDisposable
 24 
 25     {
 26 
 27         /// <summary>
 28 
 29         /// 与客户端相关联的socket
 30 
 31         /// </summary>
 32 
 33         private Socket _client;
 34 
 35  
 36 
 37         /// <summary>
 38 
 39         /// 标识是否与客户端相连接
 40 
 41         /// </summary>
 42 
 43         private bool _is_connect;
 44 
 45         public bool IsConnect
 46 
 47         {
 48 
 49             get { return _is_connect; }
 50 
 51             set { _is_connect = value; }
 52 
 53         }
 54 
 55  
 56 
 57         /// <summary>
 58 
 59         /// 数据接受缓冲区
 60 
 61         /// </summary>
 62 
 63         private byte[] _recvBuffer;
 64 
 65  
 66 
 67         public SocketClientHandle(Socket client)
 68 
 69         {
 70 
 71             this._client = client;
 72 
 73             _is_connect = true;
 74 
 75             _recvBuffer = new byte[1024 * 1024 * 2];
 76 
 77         }
 78 
 79  
 80 
 81         #region Method
 82 
 83         /// <summary>
 84 
 85         /// 接受来自客户端发来的数据
 86 
 87         /// </summary>
 88 
 89         public void RecevieData(Object state)
 90 
 91         {
 92 
 93             int len = -1;
 94 
 95             while (_is_connect)
 96 
 97             {
 98 
 99                 try
100 
101                 {
102 
103                     len = _client.Receive(_recvBuffer);
104 
105                 }
106 
107                 catch (Exception)
108 
109                 {
110 
111                     //TODO
112 
113                 }
114 
115             }
116 
117         }
118 
119  
120 
121         /// <summary>
122 
123         /// 向客户端发送数据
124 
125         /// </summary>
126 
127         public void SendData(string msg)
128 
129         {
130 
131             byte[] data = Encoding.Default.GetBytes(msg);
132 
133             try
134 
135             {
136 
137                 //有一种比较好的写法
138 
139                 _client.Send(data);
140 
141             }
142 
143             catch (Exception)
144 
145             {
146 
147                 //TODO 处理异常
148 
149             }
150 
151         }
152 
153  
154 
155         #endregion
156 
157  
158 
159  
160 
161         #region 事件
162 
163  
164 
165  
166 
167         //TODO 消息发送事件
168 
169         //TODO 数据收到事件
170 
171         //TODO 异常处理事件
172 
173  
174 
175         #endregion
176 
177  
178 
179         #region 释放
180 
181         /// <summary>
182 
183         /// Performs application-defined tasks associated with freeing, 
184 
185         /// releasing, or resetting unmanaged resources.
186 
187         /// </summary>
188 
189         public void Dispose()
190 
191         {
192 
193             _is_connect = false;
194 
195             if (_client != null)
196 
197             {
198 
199                 _client.Close();
200 
201                 _client = null;
202 
203             }
204 
205             GC.SuppressFinalize(this);
206 
207         }
208 
209  
210 
211         #endregion
212 
213     }
214 
215 }

 

Socket同步TCP服务器的时间参数类:

 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.Sock.Synchronous
12 
13 {
14 
15     /// <summary>
16 
17     /// 同步Socket TCP服务器事件类
18 
19     /// </summary>
20 
21     public class SocketEventArgs : 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 SocketClientHandle _handle;
42 
43  
44 
45         /// <summary>
46 
47         /// 是否已经处理过了
48 
49         /// </summary>
50 
51         public bool IsHandled { get; set; }
52 
53  
54 
55         public SocketEventArgs(string msg)
56 
57         {
58 
59             this._msg = msg;
60 
61             IsHandled = false;
62 
63         }
64 
65         public SocketEventArgs(SocketClientHandle handle)
66 
67         {
68 
69             this._handle = handle;
70 
71             IsHandled = false;
72 
73         }
74 
75         public SocketEventArgs(string msg, SocketClientHandle handle)
76 
77         {
78 
79             this._msg = msg;
80 
81             this._handle = handle;
82 
83             IsHandled = false;
84 
85         }
86 
87     }
88 
89 }

本文作者:小竹zz  本文地址http://blog.csdn.net/zhujunxxxxx/article/details/44258719 转载请注明出处

 

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