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

原创性声明

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

文章系列目录

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

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

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

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

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

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

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

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


本文介绍

在上一篇博客中我说了,我将会介绍c#中使用Socket和TcpListener和UdpClient实现各种同步和异步的TCP和UDP服务器,这些都是是我自己花了很多天的时间来总结的,这样一来相信刚接触c#网络编程的朋友们不会像以前的我一样到处出找资料,到处调试。本次我介绍的是使用Socket来实现的同步的TCP服务器,同步的TCP服务器和第一篇里面介绍的异步TCP服务器的区别就是,在Socket调用Accept的时候是否会阻塞。

同步的TCP服务器在接受到一个客户端的请求的时候一般是开启一个线程去处理和这个客户端的通信工作,这种方式的不好的地方就是资源消耗大,但是假如使用线程池的话,事先分配一定数量的线程,性能还是可以。

但是我之所以给出很多方法实现的服务器,主要目的就是想测试哪种情况性能比较不错,就目前来看,异步的模式比较NICE,但是其实还有一种IOCP模式性能是最好的。。。

Socket同步TCP服务器

服务端代码

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6. using System.Net;  
  7. using System.Threading;  
  8.   
  9. namespace NetFrame.Net.TCP.Sock.Synchronous  
  10. {  
  11.     /// <summary>  
  12.     /// 基于socket实现的同步TCP服务器  
  13.     /// </summary>  
  14.     public class SocketTCPServer  
  15.     {  
  16.         #region Fields  
  17.         /// <summary>  
  18.         /// 服务器程序允许的最大客户端连接数  
  19.         /// </summary>  
  20.         private int _maxClient;  
  21.   
  22.         /// <summary>  
  23.         /// 当前的连接的客户端数  
  24.         /// </summary>  
  25.         private int _clientCount;  
  26.   
  27.         /// <summary>  
  28.         /// 服务器使用的异步socket  
  29.         /// </summary>  
  30.         private Socket _serverSock;  
  31.   
  32.         /// <summary>  
  33.         /// 客户端会话列表  
  34.         /// </summary>  
  35.         private List<SocketClientHandle> _clients;  
  36.   
  37.         private bool disposed = false;  
  38.  
  39.         #endregion  
  40.  
  41.         #region Properties  
  42.   
  43.         /// <summary>  
  44.         /// 服务器是否正在运行  
  45.         /// </summary>  
  46.         public bool IsRunning { getprivate set; }  
  47.         /// <summary>  
  48.         /// 监听的IP地址  
  49.         /// </summary>  
  50.         public IPAddress Address { getprivate set; }  
  51.         /// <summary>  
  52.         /// 监听的端口  
  53.         /// </summary>  
  54.         public int Port { getprivate set; }  
  55.         /// <summary>  
  56.         /// 通信使用的编码  
  57.         /// </summary>  
  58.         public Encoding Encoding { getset; }  
  59.  
  60.  
  61.         #endregion  
  62.  
  63.         #region 构造函数  
  64.         /// <summary>  
  65.         /// 同步Socket TCP服务器  
  66.         /// </summary>  
  67.         /// <param name="listenPort">监听的端口</param>  
  68.         public SocketTCPServer(int listenPort)  
  69.             : this(IPAddress.Any, listenPort, 1024)  
  70.         {  
  71.         }  
  72.   
  73.         /// <summary>  
  74.         /// 同步Socket TCP服务器  
  75.         /// </summary>  
  76.         /// <param name="localEP">监听的终结点</param>  
  77.         public SocketTCPServer(IPEndPoint localEP)  
  78.             : this(localEP.Address, localEP.Port, 1024)  
  79.         {  
  80.         }  
  81.   
  82.         /// <summary>  
  83.         /// 同步Socket TCP服务器  
  84.         /// </summary>  
  85.         /// <param name="localIPAddress">监听的IP地址</param>  
  86.         /// <param name="listenPort">监听的端口</param>  
  87.         /// <param name="maxClient">最大客户端数量</param>  
  88.         public SocketTCPServer(IPAddress localIPAddress, int listenPort, int maxClient)  
  89.         {  
  90.             this.Address = localIPAddress;  
  91.             this.Port = listenPort;  
  92.             this.Encoding = Encoding.Default;  
  93.   
  94.             _maxClient = maxClient;  
  95.             _clients = new List<SocketClientHandle>();  
  96.             _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);  
  97.         }  
  98.  
  99.         #endregion  
  100.  
  101.         #region Method  
  102.         /// <summary>  
  103.         /// 启动服务器  
  104.         /// </summary>  
  105.         public void Start()  
  106.         {  
  107.             if (!IsRunning)  
  108.             {  
  109.                 IsRunning = true;  
  110.                 _serverSock.Bind(new IPEndPoint(this.Address, this.Port));  
  111.                 Thread thread = new Thread(StartListen);  
  112.                 thread.Start();  
  113.   
  114.             }  
  115.         }  
  116.         /// <summary>  
  117.         /// 开始进行监听  
  118.         /// </summary>  
  119.         private void StartListen()  
  120.         {  
  121.             _serverSock.Listen(1024);  
  122.             SocketClientHandle handle;  
  123.             while (IsRunning)  
  124.             {  
  125.                 if (_clientCount >= _maxClient)  
  126.                 {  
  127.                     //TODO 客户端过多异常  
  128.                     RaiseOtherException(null);  
  129.                 }  
  130.                 else  
  131.                 {  
  132.                     Socket clientSock = _serverSock.Accept();  
  133.                     _clientCount++;  
  134.                     //TODO 创建一个处理客户端的线程并启动  
  135.                     handle = new SocketClientHandle(clientSock);  
  136.                     _clients.Add(handle);  
  137.                     //使用线程池来操作  
  138.                     ThreadPool.QueueUserWorkItem(new WaitCallback(handle.RecevieData));  
  139.   
  140.                     //Thread pthread;  
  141.                     //pthread = new Thread(new ThreadStart(client.RecevieData));  
  142.                     //pthread.Start();  
  143.                     //这里应该使用线程池来进行  
  144.                 }  
  145.             }  
  146.   
  147.         }  
  148.         /// <summary>  
  149.         /// 停止服务器  
  150.         /// </summary>  
  151.         public void Stop()  
  152.         {  
  153.             if (IsRunning)  
  154.             {  
  155.                 IsRunning = false;  
  156.                 _serverSock.Close();  
  157.                 //TODO 关闭对所有客户端的连接  
  158.   
  159.             }  
  160.         }  
  161.         /// <summary>  
  162.         /// 发送函数  
  163.         /// </summary>  
  164.         public void Send(string msg, SocketClientHandle client)  
  165.         {  
  166.             //TODO  
  167.         }  
  168.   
  169.         /// <summary>  
  170.         /// 关闭一个与客户端之间的会话  
  171.         /// </summary>  
  172.         /// <param name="handle">需要关闭的客户端会话对象</param>  
  173.         public void Close(SocketClientHandle handle)  
  174.         {  
  175.             if (handle != null)  
  176.             {  
  177.                 _clients.Remove(handle);  
  178.                 handle.Dispose();  
  179.                 _clientCount--;  
  180.                 //TODO 触发关闭事件  
  181.                   
  182.             }  
  183.         }  
  184.         /// <summary>  
  185.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  186.         /// </summary>  
  187.         public void CloseAllClient()  
  188.         {  
  189.             foreach (SocketClientHandle handle in _clients)  
  190.             {  
  191.                 Close(handle);  
  192.             }  
  193.             _clientCount = 0;  
  194.             _clients.Clear();  
  195.         }  
  196.  
  197.         #endregion  
  198.  
  199.         #region 事件  
  200.   
  201.         /// <summary>  
  202.         /// 与客户端的连接已建立事件  
  203.         /// </summary>  
  204.         public event EventHandler<SocketEventArgs> ClientConnected;  
  205.         /// <summary>  
  206.         /// 与客户端的连接已断开事件  
  207.         /// </summary>  
  208.         public event EventHandler<SocketEventArgs> ClientDisconnected;  
  209.   
  210.         /// <summary>  
  211.         /// 触发客户端连接事件  
  212.         /// </summary>  
  213.         /// <param name="state"></param>  
  214.         private void RaiseClientConnected(SocketClientHandle handle)  
  215.         {  
  216.             if (ClientConnected != null)  
  217.             {  
  218.                 ClientConnected(thisnew SocketEventArgs(handle));  
  219.             }  
  220.         }  
  221.         /// <summary>  
  222.         /// 触发客户端连接断开事件  
  223.         /// </summary>  
  224.         /// <param name="client"></param>  
  225.         private void RaiseClientDisconnected(Socket client)  
  226.         {  
  227.             if (ClientDisconnected != null)  
  228.             {  
  229.                 ClientDisconnected(thisnew SocketEventArgs("连接断开"));  
  230.             }  
  231.         }  
  232.   
  233.         /// <summary>  
  234.         /// 接收到数据事件  
  235.         /// </summary>  
  236.         public event EventHandler<SocketEventArgs> DataReceived;  
  237.   
  238.         private void RaiseDataReceived(SocketClientHandle handle)  
  239.         {  
  240.             if (DataReceived != null)  
  241.             {  
  242.                 DataReceived(thisnew SocketEventArgs(handle));  
  243.             }  
  244.         }  
  245.   
  246.         /// <summary>  
  247.         /// 数据发送事件  
  248.         /// </summary>  
  249.         public event EventHandler<SocketEventArgs> CompletedSend;  
  250.   
  251.         /// <summary>  
  252.         /// 触发数据发送事件  
  253.         /// </summary>  
  254.         /// <param name="state"></param>  
  255.         private void RaiseCompletedSend(SocketClientHandle handle)  
  256.         {  
  257.             if (CompletedSend != null)  
  258.             {  
  259.                 CompletedSend(thisnew SocketEventArgs(handle));  
  260.             }  
  261.         }  
  262.   
  263.   
  264.         /// <summary>  
  265.         /// 网络错误事件  
  266.         /// </summary>  
  267.         public event EventHandler<SocketEventArgs> NetError;  
  268.         /// <summary>  
  269.         /// 触发网络错误事件  
  270.         /// </summary>  
  271.         /// <param name="state"></param>  
  272.         private void RaiseNetError(SocketClientHandle handle)  
  273.         {  
  274.             if (NetError != null)  
  275.             {  
  276.                 NetError(thisnew SocketEventArgs(handle));  
  277.             }  
  278.         }  
  279.   
  280.         /// <summary>  
  281.         /// 异常事件  
  282.         /// </summary>  
  283.         public event EventHandler<SocketEventArgs> OtherException;  
  284.         /// <summary>  
  285.         /// 触发异常事件  
  286.         /// </summary>  
  287.         /// <param name="state"></param>  
  288.         private void RaiseOtherException(SocketClientHandle handle, string descrip)  
  289.         {  
  290.             if (OtherException != null)  
  291.             {  
  292.                 OtherException(thisnew SocketEventArgs(descrip, handle));  
  293.             }  
  294.         }  
  295.         private void RaiseOtherException(SocketClientHandle handle)  
  296.         {  
  297.             RaiseOtherException(handle, "");  
  298.         }  
  299.  
  300.         #endregion  
  301.  
  302.         #region Close 未实现  
  303.         #endregion  
  304.  
  305.         #region 释放  
  306.         /// <summary>  
  307.         /// Performs application-defined tasks associated with freeing,   
  308.         /// releasing, or resetting unmanaged resources.  
  309.         /// </summary>  
  310.         public void Dispose()  
  311.         {  
  312.             Dispose(true);  
  313.             GC.SuppressFinalize(this);  
  314.         }  
  315.   
  316.         /// <summary>  
  317.         /// Releases unmanaged and - optionally - managed resources  
  318.         /// </summary>  
  319.         /// <param name="disposing"><c>true</c> to release   
  320.         /// both managed and unmanaged resources; <c>false</c>   
  321.         /// to release only unmanaged resources.</param>  
  322.         protected virtual void Dispose(bool disposing)  
  323.         {  
  324.             if (!this.disposed)  
  325.             {  
  326.                 if (disposing)  
  327.                 {  
  328.                     try  
  329.                     {  
  330.                         Stop();  
  331.                         if (_serverSock != null)  
  332.                         {  
  333.                             _serverSock = null;  
  334.                         }  
  335.                     }  
  336.                     catch (SocketException)  
  337.                     {  
  338.                         //TODO 异常  
  339.                     }  
  340.                 }  
  341.                 disposed = true;  
  342.             }  
  343.         }  
  344.         #endregion  
  345.     }  
  346. }  

对客户端操作封装的Handle类

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Net.Sockets;  
  6.   
  7. namespace NetFrame.Net.TCP.Sock.Synchronous  
  8. {  
  9.     /// <summary>  
  10.     /// Socket 服务器用于处理客户端连接封装的客户端处理类  
  11.     /// </summary>  
  12.     public class SocketClientHandle:IDisposable  
  13.     {  
  14.         /// <summary>  
  15.         /// 与客户端相关联的socket  
  16.         /// </summary>  
  17.         private Socket _client;  
  18.   
  19.         /// <summary>  
  20.         /// 标识是否与客户端相连接  
  21.         /// </summary>  
  22.         private bool _is_connect;  
  23.         public bool IsConnect  
  24.         {  
  25.             get { return _is_connect; }  
  26.             set { _is_connect = value; }  
  27.         }  
  28.   
  29.         /// <summary>  
  30.         /// 数据接受缓冲区  
  31.         /// </summary>  
  32.         private byte[] _recvBuffer;  
  33.   
  34.         public SocketClientHandle(Socket client)  
  35.         {  
  36.             this._client = client;  
  37.             _is_connect = true;  
  38.             _recvBuffer = new byte[1024 * 1024 * 2];  
  39.         }  
  40.  
  41.         #region Method  
  42.         /// <summary>  
  43.         /// 接受来自客户端发来的数据  
  44.         /// </summary>  
  45.         public void RecevieData(Object state)  
  46.         {  
  47.             int len = -1;  
  48.             while (_is_connect)  
  49.             {  
  50.                 try  
  51.                 {  
  52.                     len = _client.Receive(_recvBuffer);  
  53.                 }  
  54.                 catch (Exception)  
  55.                 {  
  56.                     //TODO  
  57.                 }  
  58.             }  
  59.         }  
  60.   
  61.         /// <summary>  
  62.         /// 向客户端发送数据  
  63.         /// </summary>  
  64.         public void SendData(string msg)  
  65.         {  
  66.             byte[] data = Encoding.Default.GetBytes(msg);  
  67.             try  
  68.             {  
  69.                 //有一种比较好的写法  
  70.                 _client.Send(data);  
  71.             }  
  72.             catch (Exception)  
  73.             {  
  74.                 //TODO 处理异常  
  75.             }  
  76.         }  
  77.  
  78.         #endregion  
  79.  
  80.  
  81.         #region 事件  
  82.   
  83.   
  84.         //TODO 消息发送事件  
  85.         //TODO 数据收到事件  
  86.         //TODO 异常处理事件  
  87.  
  88.         #endregion  
  89.  
  90.         #region 释放  
  91.         /// <summary>  
  92.         /// Performs application-defined tasks associated with freeing,   
  93.         /// releasing, or resetting unmanaged resources.  
  94.         /// </summary>  
  95.         public void Dispose()  
  96.         {  
  97.             _is_connect = false;  
  98.             if (_client != null)  
  99.             {  
  100.                 _client.Close();  
  101.                 _client = null;  
  102.             }  
  103.             GC.SuppressFinalize(this);  
  104.         }  
  105.  
  106.         #endregion  
  107.     }  
  108. }  

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

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace NetFrame.Net.TCP.Sock.Synchronous  
  7. {  
  8.     /// <summary>  
  9.     /// 同步Socket TCP服务器事件类  
  10.     /// </summary>  
  11.     public class SocketEventArgs : EventArgs  
  12.     {  
  13.         /// <summary>  
  14.         /// 提示信息  
  15.         /// </summary>  
  16.         public string _msg;  
  17.   
  18.         /// <summary>  
  19.         /// 客户端状态封装类  
  20.         /// </summary>  
  21.         public SocketClientHandle _handle;  
  22.   
  23.         /// <summary>  
  24.         /// 是否已经处理过了  
  25.         /// </summary>  
  26.         public bool IsHandled { getset; }  
  27.   
  28.         public SocketEventArgs(string msg)  
  29.         {  
  30.             this._msg = msg;  
  31.             IsHandled = false;  
  32.         }  
  33.         public SocketEventArgs(SocketClientHandle handle)  
  34.         {  
  35.             this._handle = handle;  
  36.             IsHandled = false;  
  37.         }  
  38.         public SocketEventArgs(string msg, SocketClientHandle handle)  
  39.         {  
  40.             this._msg = msg;  
  41.             this._handle = handle;  
  42.             IsHandled = false;  
  43.         }  
  44.     }  
  45. }  

本文作者:小竹zz  本文地址http://blog.youkuaiyun.com/zhujunxxxxx/article/details/44258719 转载请注明出处
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值