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

29 篇文章 0 订阅

原创性声明

本文作者:小竹zz 本文地址http://blog.csdn.net/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服务器

本文介绍

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

TcpListener同步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.Listener.Synchronous  
  10. {  
  11.     /// <summary>  
  12.     /// TcpListener实现同步TCP服务器  
  13.     /// </summary>  
  14.     public class TCPServer  
  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.         /// 服务器使用的异步TcpListener  
  29.         /// </summary>  
  30.         private TcpListener _listener;  
  31.   
  32.         /// <summary>  
  33.         /// 客户端会话列表  
  34.         /// </summary>  
  35.         private List<TCPClientHandle> _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.         #endregion  
  61.  
  62.         #region 构造器  
  63.         /// <summary>  
  64.         /// 同步TCP服务器  
  65.         /// </summary>  
  66.         /// <param name="listenPort">监听的端口</param>  
  67.         public TCPServer(int listenPort)  
  68.             : this(IPAddress.Any, listenPort, 1024)  
  69.         {  
  70.         }  
  71.   
  72.         /// <summary>  
  73.         /// 同步TCP服务器  
  74.         /// </summary>  
  75.         /// <param name="localEP">监听的终结点</param>  
  76.         public TCPServer(IPEndPoint localEP)  
  77.             : this(localEP.Address, localEP.Port, 1024)  
  78.         {  
  79.         }  
  80.   
  81.         /// <summary>  
  82.         /// 同步TCP服务器  
  83.         /// </summary>  
  84.         /// <param name="localIPAddress">监听的IP地址</param>  
  85.         /// <param name="listenPort">监听的端口</param>  
  86.         /// <param name="maxClient">最大客户端数量</param>  
  87.         public TCPServer(IPAddress localIPAddress, int listenPort, int maxClient)  
  88.         {  
  89.             this.Address = localIPAddress;  
  90.             this.Port = listenPort;  
  91.             this.Encoding = Encoding.Default;  
  92.   
  93.             _maxClient = maxClient;  
  94.             _clients = new List<TCPClientHandle>();  
  95.             _listener = new TcpListener(new IPEndPoint(this.Address, this.Port));  
  96.         }  
  97.  
  98.         #endregion  
  99.  
  100.         #region Method  
  101.         /// <summary>  
  102.         /// 启动服务器  
  103.         /// </summary>  
  104.         public void Start()  
  105.         {  
  106.             if (!IsRunning)  
  107.             {  
  108.                 IsRunning = true;  
  109.                 _listener.Start();  
  110.                 Thread thread = new Thread(Accept);  
  111.                 thread.Start();  
  112.             }  
  113.         }  
  114.         /// <summary>  
  115.         /// 开始进行监听  
  116.         /// </summary>  
  117.         private void Accept()  
  118.         {  
  119.             TCPClientHandle handle;  
  120.             while (IsRunning)  
  121.             {  
  122.                 TcpClient client = _listener.AcceptTcpClient();  
  123.                 if (_clientCount >= _maxClient)  
  124.                 {  
  125.                     //TODO 触发事件  
  126.                 }  
  127.                 else  
  128.                 {  
  129.                     handle = new TCPClientHandle(client);  
  130.                     _clientCount++;  
  131.                     _clients.Add(handle);  
  132.   
  133.                     //TODO 创建一个处理客户端的线程并启动  
  134.                     //使用线程池来操作  
  135.                     new Thread(new ThreadStart(handle.RecevieData)).Start();  
  136.                 }  
  137.             }  
  138.   
  139.         }  
  140.         /// <summary>  
  141.         /// 停止服务器  
  142.         /// </summary>  
  143.         public void Stop()  
  144.         {  
  145.             if (IsRunning)  
  146.             {  
  147.                 IsRunning = false;  
  148.                 _listener.Stop();  
  149.                 //TODO 关闭对所有客户端的连接  
  150.             }  
  151.         }  
  152.         /// <summary>  
  153.         /// 发送函数  
  154.         /// </summary>  
  155.         public void Send(string msg, TcpClient client)  
  156.         {  
  157.             //TODO  
  158.         }  
  159.  
  160.         #endregion  
  161.  
  162.         #region 事件  
  163.   
  164.         /// <summary>  
  165.         /// 与客户端的连接已建立事件  
  166.         /// </summary>  
  167.         public event EventHandler<TCPEventArgs> ClientConnected;  
  168.         /// <summary>  
  169.         /// 与客户端的连接已断开事件  
  170.         /// </summary>  
  171.         public event EventHandler<TCPEventArgs> ClientDisconnected;  
  172.   
  173.         /// <summary>  
  174.         /// 触发客户端连接事件  
  175.         /// </summary>  
  176.         /// <param name="state"></param>  
  177.         private void RaiseClientConnected(TCPClientHandle handle)  
  178.         {  
  179.             if (ClientConnected != null)  
  180.             {  
  181.                 ClientConnected(thisnew TCPEventArgs(handle));  
  182.             }  
  183.         }  
  184.         /// <summary>  
  185.         /// 触发客户端连接断开事件  
  186.         /// </summary>  
  187.         /// <param name="client"></param>  
  188.         private void RaiseClientDisconnected(Socket client)  
  189.         {  
  190.             if (ClientDisconnected != null)  
  191.             {  
  192.                 ClientDisconnected(thisnew TCPEventArgs("连接断开"));  
  193.             }  
  194.         }  
  195.   
  196.         /// <summary>  
  197.         /// 接收到数据事件  
  198.         /// </summary>  
  199.         public event EventHandler<TCPEventArgs> DataReceived;  
  200.   
  201.         private void RaiseDataReceived(TCPClientHandle handle)  
  202.         {  
  203.             if (DataReceived != null)  
  204.             {  
  205.                 DataReceived(thisnew TCPEventArgs(handle));  
  206.             }  
  207.         }  
  208.   
  209.         /// <summary>  
  210.         /// 数据发送事件  
  211.         /// </summary>  
  212.         public event EventHandler<TCPEventArgs> CompletedSend;  
  213.   
  214.         /// <summary>  
  215.         /// 触发数据发送事件  
  216.         /// </summary>  
  217.         /// <param name="state"></param>  
  218.         private void RaiseCompletedSend(TCPClientHandle handle)  
  219.         {  
  220.             if (CompletedSend != null)  
  221.             {  
  222.                 CompletedSend(thisnew TCPEventArgs(handle));  
  223.             }  
  224.         }  
  225.   
  226.   
  227.         /// <summary>  
  228.         /// 网络错误事件  
  229.         /// </summary>  
  230.         public event EventHandler<TCPEventArgs> NetError;  
  231.         /// <summary>  
  232.         /// 触发网络错误事件  
  233.         /// </summary>  
  234.         /// <param name="state"></param>  
  235.         private void RaiseNetError(TCPClientHandle handle)  
  236.         {  
  237.             if (NetError != null)  
  238.             {  
  239.                 NetError(thisnew TCPEventArgs(handle));  
  240.             }  
  241.         }  
  242.   
  243.         /// <summary>  
  244.         /// 异常事件  
  245.         /// </summary>  
  246.         public event EventHandler<TCPEventArgs> OtherException;  
  247.         /// <summary>  
  248.         /// 触发异常事件  
  249.         /// </summary>  
  250.         /// <param name="state"></param>  
  251.         private void RaiseOtherException(TCPClientHandle handle, string descrip)  
  252.         {  
  253.             if (OtherException != null)  
  254.             {  
  255.                 OtherException(thisnew TCPEventArgs(descrip, handle));  
  256.             }  
  257.         }  
  258.         private void RaiseOtherException(TCPClientHandle handle)  
  259.         {  
  260.             RaiseOtherException(handle, "");  
  261.         }  
  262.  
  263.         #endregion  
  264.  
  265.         #region Close  
  266.   
  267.         /// <summary>  
  268.         /// 关闭一个与客户端之间的会话  
  269.         /// </summary>  
  270.         /// <param name="handle">需要关闭的客户端会话对象</param>  
  271.         public void Close(TCPClientHandle handle)  
  272.         {  
  273.             if (handle != null)  
  274.             {  
  275.                 _clients.Remove(handle);  
  276.                 handle.Dispose();  
  277.                 _clientCount--;  
  278.                 //TODO 触发关闭事件  
  279.   
  280.             }  
  281.         }  
  282.         /// <summary>  
  283.         /// 关闭所有的客户端会话,与所有的客户端连接会断开  
  284.         /// </summary>  
  285.         public void CloseAllClient()  
  286.         {  
  287.             foreach (TCPClientHandle handle in _clients)  
  288.             {  
  289.                 Close(handle);  
  290.             }  
  291.             _clientCount = 0;  
  292.             _clients.Clear();  
  293.         }  
  294.         #endregion  
  295.  
  296.         #region 释放  
  297.         /// <summary>  
  298.         /// Performs application-defined tasks associated with freeing,   
  299.         /// releasing, or resetting unmanaged resources.  
  300.         /// </summary>  
  301.         public void Dispose()  
  302.         {  
  303.             Dispose(true);  
  304.             GC.SuppressFinalize(this);  
  305.         }  
  306.   
  307.         /// <summary>  
  308.         /// Releases unmanaged and - optionally - managed resources  
  309.         /// </summary>  
  310.         /// <param name="disposing"><c>true</c> to release   
  311.         /// both managed and unmanaged resources; <c>false</c>   
  312.         /// to release only unmanaged resources.</param>  
  313.         protected virtual void Dispose(bool disposing)  
  314.         {  
  315.             if (!this.disposed)  
  316.             {  
  317.                 if (disposing)  
  318.                 {  
  319.                     try  
  320.                     {  
  321.                         Stop();  
  322.                         if (_listener != null)  
  323.                         {  
  324.                             _listener = null;  
  325.                         }  
  326.                     }  
  327.                     catch (SocketException)  
  328.                     {  
  329.                         //TODO 异常  
  330.                     }  
  331.                 }  
  332.                 disposed = true;  
  333.             }  
  334.         }  
  335.         #endregion  
  336.     }  
  337. }  
客户端处理封装类

[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.IO;  
  7.   
  8. namespace NetFrame.Net.TCP.Listener.Synchronous  
  9. {  
  10.     /// <summary>  
  11.     /// TcpListener实现同步TCP服务器 的客户端连接处理类  
  12.     /// </summary>  
  13.     public class TCPClientHandle  
  14.     {  
  15.         private TcpClient _tcpclient;  
  16.   
  17.         private BinaryReader rs;  
  18.   
  19.         private BinaryWriter ws;  
  20.   
  21.         /// <summary>  
  22.         /// 标识是否与客户端相连接  
  23.         /// </summary>  
  24.         private bool _is_connect;  
  25.         public bool IsConnect  
  26.         {  
  27.             get { return _is_connect; }  
  28.             set { _is_connect = value; }  
  29.         }  
  30.   
  31.         /// <summary>  
  32.         /// 数据接受缓冲区  
  33.         /// </summary>  
  34.         private byte[] _recvBuffer;  
  35.   
  36.         public TCPClientHandle(TcpClient client)  
  37.         {  
  38.             _tcpclient = client;  
  39.             rs = new BinaryReader(client.GetStream());  
  40.             ws = new BinaryWriter(client.GetStream());  
  41.             // NetworkStream ns = tmpTcpClient.GetStream();  
  42.             // if(ns.CanRead&&ns.CanWrite)  
  43.             _recvBuffer=new byte[client.ReceiveBufferSize];  
  44.         }  
  45.   
  46.         /// <summary>  
  47.         /// 接受数据  
  48.         /// </summary>  
  49.         public void RecevieData()  
  50.         {  
  51.             int len = 0;  
  52.             while (_is_connect)  
  53.             {  
  54.                 try  
  55.                 {  
  56.                     len = rs.Read(_recvBuffer, 0, _recvBuffer.Length);  
  57.                 }  
  58.                 catch (Exception)  
  59.                 {  
  60.                     break;  
  61.                 }  
  62.                 if (len == 0)  
  63.                 {  
  64.                     //the client has disconnected from server  
  65.                     break;  
  66.                 }  
  67.                 //TODO 处理收到的数据  
  68.                   
  69.             }  
  70.         }  
  71.         /// <summary>  
  72.         /// 向客户端发送数据  
  73.         /// </summary>  
  74.         /// <param name="msg"></param>  
  75.         public void SendData(string msg)  
  76.         {  
  77.             byte[] data = Encoding.Default.GetBytes(msg);  
  78.             try  
  79.             {  
  80.                 ws.Write(data, 0, data.Length);  
  81.                 ws.Flush();  
  82.             }  
  83.             catch (Exception)  
  84.             {  
  85.                 //TODO 处理异常  
  86.             }  
  87.         }  
  88.  
  89.         #region 事件  
  90.   
  91.   
  92.         //TODO 消息发送事件  
  93.         //TODO 数据收到事件  
  94.         //TODO 异常处理事件  
  95.  
  96.         #endregion  
  97.  
  98.         #region 释放  
  99.         /// <summary>  
  100.         /// Performs application-defined tasks associated with freeing,   
  101.         /// releasing, or resetting unmanaged resources.  
  102.         /// </summary>  
  103.         public void Dispose()  
  104.         {  
  105.             _is_connect = false;  
  106.             if (_tcpclient != null)  
  107.             {  
  108.                 _tcpclient.Close();  
  109.                 _tcpclient = null;  
  110.             }  
  111.             GC.SuppressFinalize(this);  
  112.         }  
  113.  
  114.         #endregion  
  115.     }  
  116. }  

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.Listener.Synchronous  
  7. {  
  8.     /// <summary>  
  9.     /// 同步TcpListener TCP服务器事件类  
  10.     /// </summary>  
  11.     public class TCPEventArgs : EventArgs  
  12.     {  
  13.         /// <summary>  
  14.         /// 提示信息  
  15.         /// </summary>  
  16.         public string _msg;  
  17.   
  18.         /// <summary>  
  19.         /// 客户端状态封装类  
  20.         /// </summary>  
  21.         public TCPClientHandle _handle;  
  22.   
  23.         /// <summary>  
  24.         /// 是否已经处理过了  
  25.         /// </summary>  
  26.         public bool IsHandled { getset; }  
  27.   
  28.         public TCPEventArgs(string msg)  
  29.         {  
  30.             this._msg = msg;  
  31.             IsHandled = false;  
  32.         }  
  33.         public TCPEventArgs(TCPClientHandle handle)  
  34.         {  
  35.             this._handle = handle;  
  36.             IsHandled = false;  
  37.         }  
  38.         public TCPEventArgs(string msg, TCPClientHandle handle)  
  39.         {  
  40.             this._msg = msg;  
  41.             this._handle = handle;  
  42.             IsHandled = false;  
  43.         }  
  44.     }  
  45. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值