zoukankan      html  css  js  c++  java
  • C# 对 TCP 客户端的状态封装

    TCP客户端连接TCP服务器端有几种应用状态:

    1. 与服务器的连接已建立
    2. 与服务器的连接已断开
    3. 与服务器的连接发生异常

    应用程序可按需求合理处理这些逻辑,比如:

    1. 连接断开后自动重连
    2. 连接断开后选择备用地址重连
    3. 所有状态变化上报告警

    本文描述的TcpClient实现了状态变化的事件通知机制。

    复制代码
      1   /// <summary>
      2   /// 异步TCP客户端
      3   /// </summary>
      4   public class AsyncTcpClient : IDisposable
      5   {
      6     #region Fields
      7 
      8     private TcpClient tcpClient;
      9     private bool disposed = false;
     10     private int retries = 0;
     11 
     12     #endregion
     13 
     14     #region Ctors
     15 
     16     /// <summary>
     17     /// 异步TCP客户端
     18     /// </summary>
     19     /// <param name="remoteEP">远端服务器终结点</param>
     20     public AsyncTcpClient(IPEndPoint remoteEP)
     21       : this(new[] { remoteEP.Address }, remoteEP.Port)
     22     {
     23     }
     24 
     25     /// <summary>
     26     /// 异步TCP客户端
     27     /// </summary>
     28     /// <param name="remoteEP">远端服务器终结点</param>
     29     /// <param name="localEP">本地客户端终结点</param>
     30     public AsyncTcpClient(IPEndPoint remoteEP, IPEndPoint localEP)
     31       : this(new[] { remoteEP.Address }, remoteEP.Port, localEP)
     32     {
     33     }
     34 
     35     /// <summary>
     36     /// 异步TCP客户端
     37     /// </summary>
     38     /// <param name="remoteIPAddress">远端服务器IP地址</param>
     39     /// <param name="remotePort">远端服务器端口</param>
     40     public AsyncTcpClient(IPAddress remoteIPAddress, int remotePort)
     41       : this(new[] { remoteIPAddress }, remotePort)
     42     {
     43     }
     44 
     45     /// <summary>
     46     /// 异步TCP客户端
     47     /// </summary>
     48     /// <param name="remoteIPAddress">远端服务器IP地址</param>
     49     /// <param name="remotePort">远端服务器端口</param>
     50     /// <param name="localEP">本地客户端终结点</param>
     51     public AsyncTcpClient(
     52       IPAddress remoteIPAddress, int remotePort, IPEndPoint localEP)
     53       : this(new[] { remoteIPAddress }, remotePort, localEP)
     54     {
     55     }
     56 
     57     /// <summary>
     58     /// 异步TCP客户端
     59     /// </summary>
     60     /// <param name="remoteHostName">远端服务器主机名</param>
     61     /// <param name="remotePort">远端服务器端口</param>
     62     public AsyncTcpClient(string remoteHostName, int remotePort)
     63       : this(Dns.GetHostAddresses(remoteHostName), remotePort)
     64     {
     65     }
     66 
     67     /// <summary>
     68     /// 异步TCP客户端
     69     /// </summary>
     70     /// <param name="remoteHostName">远端服务器主机名</param>
     71     /// <param name="remotePort">远端服务器端口</param>
     72     /// <param name="localEP">本地客户端终结点</param>
     73     public AsyncTcpClient(
     74       string remoteHostName, int remotePort, IPEndPoint localEP)
     75       : this(Dns.GetHostAddresses(remoteHostName), remotePort, localEP)
     76     {
     77     }
     78 
     79     /// <summary>
     80     /// 异步TCP客户端
     81     /// </summary>
     82     /// <param name="remoteIPAddresses">远端服务器IP地址列表</param>
     83     /// <param name="remotePort">远端服务器端口</param>
     84     public AsyncTcpClient(IPAddress[] remoteIPAddresses, int remotePort)
     85       : this(remoteIPAddresses, remotePort, null)
     86     {
     87     }
     88 
     89     /// <summary>
     90     /// 异步TCP客户端
     91     /// </summary>
     92     /// <param name="remoteIPAddresses">远端服务器IP地址列表</param>
     93     /// <param name="remotePort">远端服务器端口</param>
     94     /// <param name="localEP">本地客户端终结点</param>
     95     public AsyncTcpClient(
     96       IPAddress[] remoteIPAddresses, int remotePort, IPEndPoint localEP)
     97     {
     98       this.Addresses = remoteIPAddresses;
     99       this.Port = remotePort;
    100       this.LocalIPEndPoint = localEP;
    101       this.Encoding = Encoding.Default;
    102 
    103       if (this.LocalIPEndPoint != null)
    104       {
    105         this.tcpClient = new TcpClient(this.LocalIPEndPoint);
    106       }
    107       else
    108       {
    109         this.tcpClient = new TcpClient();
    110       }
    111 
    112       Retries = 3;
    113       RetryInterval = 5;
    114     }
    115 
    116     #endregion
    117 
    118     #region Properties
    119 
    120     /// <summary>
    121     /// 是否已与服务器建立连接
    122     /// </summary>
    123     public bool Connected { get { return tcpClient.Client.Connected; } }
    124     /// <summary>
    125     /// 远端服务器的IP地址列表
    126     /// </summary>
    127     public IPAddress[] Addresses { get; private set; }
    128     /// <summary>
    129     /// 远端服务器的端口
    130     /// </summary>
    131     public int Port { get; private set; }
    132     /// <summary>
    133     /// 连接重试次数
    134     /// </summary>
    135     public int Retries { get; set; }
    136     /// <summary>
    137     /// 连接重试间隔
    138     /// </summary>
    139     public int RetryInterval { get; set; }
    140     /// <summary>
    141     /// 远端服务器终结点
    142     /// </summary>
    143     public IPEndPoint RemoteIPEndPoint 
    144     { 
    145       get { return new IPEndPoint(Addresses[0], Port); } 
    146     }
    147     /// <summary>
    148     /// 本地客户端终结点
    149     /// </summary>
    150     protected IPEndPoint LocalIPEndPoint { get; private set; }
    151     /// <summary>
    152     /// 通信所使用的编码
    153     /// </summary>
    154     public Encoding Encoding { get; set; }
    155 
    156     #endregion
    157 
    158     #region Connect
    159 
    160     /// <summary>
    161     /// 连接到服务器
    162     /// </summary>
    163     /// <returns>异步TCP客户端</returns>
    164     public AsyncTcpClient Connect()
    165     {
    166       if (!Connected)
    167       {
    168         // start the async connect operation
    169         tcpClient.BeginConnect(
    170           Addresses, Port, HandleTcpServerConnected, tcpClient);
    171       }
    172 
    173       return this;
    174     }
    175 
    176     /// <summary>
    177     /// 关闭与服务器的连接
    178     /// </summary>
    179     /// <returns>异步TCP客户端</returns>
    180     public AsyncTcpClient Close()
    181     {
    182       if (Connected)
    183       {
    184         retries = 0;
    185         tcpClient.Close();
    186         RaiseServerDisconnected(Addresses, Port);
    187       }
    188 
    189       return this;
    190     }
    191 
    192     #endregion
    193 
    194     #region Receive
    195 
    196     private void HandleTcpServerConnected(IAsyncResult ar)
    197     {
    198       try
    199       {
    200         tcpClient.EndConnect(ar);
    201         RaiseServerConnected(Addresses, Port);
    202         retries = 0;
    203       }
    204       catch (Exception ex)
    205       {
    206         ExceptionHandler.Handle(ex);
    207         if (retries > 0)
    208         {
    209           Logger.Debug(string.Format(CultureInfo.InvariantCulture, 
    210             "Connect to server with retry {0} failed.", retries));
    211         }
    212 
    213         retries++;
    214         if (retries > Retries)
    215         {
    216           // we have failed to connect to all the IP Addresses, 
    217           // connection has failed overall.
    218           RaiseServerExceptionOccurred(Addresses, Port, ex);
    219           return;
    220         }
    221         else
    222         {
    223           Logger.Debug(string.Format(CultureInfo.InvariantCulture, 
    224             "Waiting {0} seconds before retrying to connect to server.", 
    225             RetryInterval));
    226           Thread.Sleep(TimeSpan.FromSeconds(RetryInterval));
    227           Connect();
    228           return;
    229         }
    230       }
    231 
    232       // we are connected successfully and start asyn read operation.
    233       byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
    234       tcpClient.GetStream().BeginRead(
    235         buffer, 0, buffer.Length, HandleDatagramReceived, buffer);
    236     }
    237 
    238     private void HandleDatagramReceived(IAsyncResult ar)
    239     {
    240       NetworkStream stream = tcpClient.GetStream();
    241 
    242       int numberOfReadBytes = 0;
    243       try
    244       {
    245         numberOfReadBytes = stream.EndRead(ar);
    246       }
    247       catch
    248       {
    249         numberOfReadBytes = 0;
    250       }
    251 
    252       if (numberOfReadBytes == 0)
    253       {
    254         // connection has been closed
    255         Close();
    256         return;
    257       }
    258 
    259       // received byte and trigger event notification
    260       byte[] buffer = (byte[])ar.AsyncState;
    261       byte[] receivedBytes = new byte[numberOfReadBytes];
    262       Buffer.BlockCopy(buffer, 0, receivedBytes, 0, numberOfReadBytes);
    263       RaiseDatagramReceived(tcpClient, receivedBytes);
    264       RaisePlaintextReceived(tcpClient, receivedBytes);
    265 
    266       // then start reading from the network again
    267       stream.BeginRead(
    268         buffer, 0, buffer.Length, HandleDatagramReceived, buffer);
    269     }
    270 
    271     #endregion
    272 
    273     #region Events
    274 
    275     /// <summary>
    276     /// 接收到数据报文事件
    277     /// </summary>
    278     public event EventHandler<TcpDatagramReceivedEventArgs<byte[]>> DatagramReceived;
    279     /// <summary>
    280     /// 接收到数据报文明文事件
    281     /// </summary>
    282     public event EventHandler<TcpDatagramReceivedEventArgs<string>> PlaintextReceived;
    283 
    284     private void RaiseDatagramReceived(TcpClient sender, byte[] datagram)
    285     {
    286       if (DatagramReceived != null)
    287       {
    288         DatagramReceived(this, 
    289           new TcpDatagramReceivedEventArgs<byte[]>(sender, datagram));
    290       }
    291     }
    292 
    293     private void RaisePlaintextReceived(TcpClient sender, byte[] datagram)
    294     {
    295       if (PlaintextReceived != null)
    296       {
    297         PlaintextReceived(this, 
    298           new TcpDatagramReceivedEventArgs<string>(
    299             sender, this.Encoding.GetString(datagram, 0, datagram.Length)));
    300       }
    301     }
    302 
    303     /// <summary>
    304     /// 与服务器的连接已建立事件
    305     /// </summary>
    306     public event EventHandler<TcpServerConnectedEventArgs> ServerConnected;
    307     /// <summary>
    308     /// 与服务器的连接已断开事件
    309     /// </summary>
    310     public event EventHandler<TcpServerDisconnectedEventArgs> ServerDisconnected;
    311     /// <summary>
    312     /// 与服务器的连接发生异常事件
    313     /// </summary>
    314     public event EventHandler<TcpServerExceptionOccurredEventArgs> ServerExceptionOccurred;
    315 
    316     private void RaiseServerConnected(IPAddress[] ipAddresses, int port)
    317     {
    318       if (ServerConnected != null)
    319       {
    320         ServerConnected(this, 
    321           new TcpServerConnectedEventArgs(ipAddresses, port));
    322       }
    323     }
    324 
    325     private void RaiseServerDisconnected(IPAddress[] ipAddresses, int port)
    326     {
    327       if (ServerDisconnected != null)
    328       {
    329         ServerDisconnected(this, 
    330           new TcpServerDisconnectedEventArgs(ipAddresses, port));
    331       }
    332     }
    333 
    334     private void RaiseServerExceptionOccurred(
    335       IPAddress[] ipAddresses, int port, Exception innerException)
    336     {
    337       if (ServerExceptionOccurred != null)
    338       {
    339         ServerExceptionOccurred(this, 
    340           new TcpServerExceptionOccurredEventArgs(
    341             ipAddresses, port, innerException));
    342       }
    343     }
    344 
    345     #endregion
    346 
    347     #region Send
    348 
    349     /// <summary>
    350     /// 发送报文
    351     /// </summary>
    352     /// <param name="datagram">报文</param>
    353     public void Send(byte[] datagram)
    354     {
    355       if (datagram == null)
    356         throw new ArgumentNullException("datagram");
    357 
    358       if (!Connected)
    359       {
    360         RaiseServerDisconnected(Addresses, Port);
    361         throw new InvalidProgramException(
    362           "This client has not connected to server.");
    363       }
    364 
    365       tcpClient.GetStream().BeginWrite(
    366         datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);
    367     }
    368 
    369     private void HandleDatagramWritten(IAsyncResult ar)
    370     {
    371       ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
    372     }
    373 
    374     /// <summary>
    375     /// 发送报文
    376     /// </summary>
    377     /// <param name="datagram">报文</param>
    378     public void Send(string datagram)
    379     {
    380       Send(this.Encoding.GetBytes(datagram));
    381     }
    382 
    383     #endregion
    384 
    385     #region IDisposable Members
    386 
    387     /// <summary>
    388     /// Performs application-defined tasks associated with freeing, 
    389     /// releasing, or resetting unmanaged resources.
    390     /// </summary>
    391     public void Dispose()
    392     {
    393       Dispose(true);
    394       GC.SuppressFinalize(this);
    395     }
    396 
    397     /// <summary>
    398     /// Releases unmanaged and - optionally - managed resources
    399     /// </summary>
    400     /// <param name="disposing"><c>true</c> to release both managed 
    401     /// and unmanaged resources; <c>false</c> 
    402     /// to release only unmanaged resources.
    403     /// </param>
    404     protected virtual void Dispose(bool disposing)
    405     {
    406       if (!this.disposed)
    407       {
    408         if (disposing)
    409         {
    410           try
    411           {
    412             Close();
    413 
    414             if (tcpClient != null)
    415             {
    416               tcpClient = null;
    417             }
    418           }
    419           catch (SocketException ex)
    420           {
    421             ExceptionHandler.Handle(ex);
    422           }
    423         }
    424 
    425         disposed = true;
    426       }
    427     }
    428 
    429     #endregion
    430   }
    复制代码

    使用举例

    复制代码
     1   class Program
     2   {
     3     static AsyncTcpClient client;
     4 
     5     static void Main(string[] args)
     6     {
     7       LogFactory.Assign(new ConsoleLogFactory());
     8 
     9       // 测试用,可以不指定由系统选择端口
    10       IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999);
    11       IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9998); 
    12       client = new AsyncTcpClient(remoteEP, localEP);
    13       client.Encoding = Encoding.UTF8;
    14       client.ServerExceptionOccurred += 
    15         new EventHandler<TcpServerExceptionOccurredEventArgs>(client_ServerExceptionOccurred);
    16       client.ServerConnected += 
    17         new EventHandler<TcpServerConnectedEventArgs>(client_ServerConnected);
    18       client.ServerDisconnected += 
    19         new EventHandler<TcpServerDisconnectedEventArgs>(client_ServerDisconnected);
    20       client.PlaintextReceived += 
    21         new EventHandler<TcpDatagramReceivedEventArgs<string>>(client_PlaintextReceived);
    22       client.Connect();
    23 
    24       Console.WriteLine("TCP client has connected to server.");
    25       Console.WriteLine("Type something to send to server...");
    26       while (true)
    27       {
    28         try
    29         {
    30           string text = Console.ReadLine();
    31           client.Send(text);
    32         }
    33         catch (Exception ex)
    34         {
    35           Console.WriteLine(ex.Message);
    36         }
    37       }
    38     }
    39 
    40     static void client_ServerExceptionOccurred(
    41       object sender, TcpServerExceptionOccurredEventArgs e)
    42     {
    43       Logger.Debug(string.Format(CultureInfo.InvariantCulture, 
    44         "TCP server {0} exception occurred, {1}.", 
    45         e.ToString(), e.Exception.Message));
    46     }
    47 
    48     static void client_ServerConnected(
    49       object sender, TcpServerConnectedEventArgs e)
    50     {
    51       Logger.Debug(string.Format(CultureInfo.InvariantCulture, 
    52         "TCP server {0} has connected.", e.ToString()));
    53     }
    54 
    55     static void client_ServerDisconnected(
    56       object sender, TcpServerDisconnectedEventArgs e)
    57     {
    58       Logger.Debug(string.Format(CultureInfo.InvariantCulture, 
    59         "TCP server {0} has disconnected.", e.ToString()));
    60     }
    61 
    62     static void client_PlaintextReceived(
    63       object sender, TcpDatagramReceivedEventArgs<string> e)
    64     {
    65       Console.Write(string.Format("Server : {0} --> ", 
    66         e.TcpClient.Client.RemoteEndPoint.ToString()));
    67       Console.WriteLine(string.Format("{0}", e.Datagram));
    68     }
    69   }
    复制代码

    TCP客户端State

    复制代码
     1   /// <summary>
     2   /// Internal class to join the TCP client and buffer together
     3   /// for easy management in the server
     4   /// </summary>
     5   internal class TcpClientState
     6   {
     7     /// <summary>
     8     /// Constructor for a new Client
     9     /// </summary>
    10     /// <param name="tcpClient">The TCP client</param>
    11     /// <param name="buffer">The byte array buffer</param>
    12     public TcpClientState(TcpClient tcpClient, byte[] buffer)
    13     {
    14       if (tcpClient == null)
    15         throw new ArgumentNullException("tcpClient");
    16       if (buffer == null)
    17         throw new ArgumentNullException("buffer");
    18 
    19       this.TcpClient = tcpClient;
    20       this.Buffer = buffer;
    21     }
    22 
    23     /// <summary>
    24     /// Gets the TCP Client
    25     /// </summary>
    26     public TcpClient TcpClient { get; private set; }
    27 
    28     /// <summary>
    29     /// Gets the Buffer.
    30     /// </summary>
    31     public byte[] Buffer { get; private set; }
    32 
    33     /// <summary>
    34     /// Gets the network stream
    35     /// </summary>
    36     public NetworkStream NetworkStream
    37     {
    38       get { return TcpClient.GetStream(); }
    39     }
    40   }
    复制代码

    与客户端的连接已建立事件参数

    复制代码
     1   /// <summary>
     2   /// 与客户端的连接已建立事件参数
     3   /// </summary>
     4   public class TcpClientConnectedEventArgs : EventArgs
     5   {
     6     /// <summary>
     7     /// 与客户端的连接已建立事件参数
     8     /// </summary>
     9     /// <param name="tcpClient">客户端</param>
    10     public TcpClientConnectedEventArgs(TcpClient tcpClient)
    11     {
    12       if (tcpClient == null)
    13         throw new ArgumentNullException("tcpClient");
    14 
    15       this.TcpClient = tcpClient;
    16     }
    17 
    18     /// <summary>
    19     /// 客户端
    20     /// </summary>
    21     public TcpClient TcpClient { get; private set; }
    22   }
    复制代码

    与客户端的连接已断开事件参数

    复制代码
      /// <summary>
      /// 与客户端的连接已断开事件参数
      /// </summary>
      public class TcpClientDisconnectedEventArgs : EventArgs
      {
        /// <summary>
        /// 与客户端的连接已断开事件参数
        /// </summary>
        /// <param name="tcpClient">客户端</param>
        public TcpClientDisconnectedEventArgs(TcpClient tcpClient)
        {
          if (tcpClient == null)
            throw new ArgumentNullException("tcpClient");
    
          this.TcpClient = tcpClient;
        }
    
        /// <summary>
        /// 客户端
        /// </summary>
        public TcpClient TcpClient { get; private set; }
      }
    复制代码

    与服务器的连接发生异常事件参数

    复制代码
     1   /// <summary>
     2   /// 与服务器的连接发生异常事件参数
     3   /// </summary>
     4   public class TcpServerExceptionOccurredEventArgs : EventArgs
     5   {
     6     /// <summary>
     7     /// 与服务器的连接发生异常事件参数
     8     /// </summary>
     9     /// <param name="ipAddresses">服务器IP地址列表</param>
    10     /// <param name="port">服务器端口</param>
    11     /// <param name="innerException">内部异常</param>
    12     public TcpServerExceptionOccurredEventArgs(
    13       IPAddress[] ipAddresses, int port, Exception innerException)
    14     {
    15       if (ipAddresses == null)
    16         throw new ArgumentNullException("ipAddresses");
    17 
    18       this.Addresses = ipAddresses;
    19       this.Port = port;
    20       this.Exception = innerException;
    21     }
    22 
    23     /// <summary>
    24     /// 服务器IP地址列表
    25     /// </summary>
    26     public IPAddress[] Addresses { get; private set; }
    27     /// <summary>
    28     /// 服务器端口
    29     /// </summary>
    30     public int Port { get; private set; }
    31     /// <summary>
    32     /// 内部异常
    33     /// </summary>
    34     public Exception Exception { get; private set; }
    35 
    36     /// <summary>
    37     /// Returns a <see cref="System.String"/> that represents this instance.
    38     /// </summary>
    39     /// <returns>
    40     /// A <see cref="System.String"/> that represents this instance.
    41     /// </returns>
    42     public override string ToString()
    43     {
    44       string s = string.Empty;
    45       foreach (var item in Addresses)
    46       {
    47         s = s + item.ToString() + ',';
    48       }
    49       s = s.TrimEnd(',');
    50       s = s + ":" + Port.ToString(CultureInfo.InvariantCulture);
    51 
    52       return s;
    53     }
    54   }
    复制代码

    接收到数据报文事件参数

    复制代码
     1   /// <summary>
     2   /// 接收到数据报文事件参数
     3   /// </summary>
     4   /// <typeparam name="T">报文类型</typeparam>
     5   public class TcpDatagramReceivedEventArgs<T> : EventArgs
     6   {
     7     /// <summary>
     8     /// 接收到数据报文事件参数
     9     /// </summary>
    10     /// <param name="tcpClient">客户端</param>
    11     /// <param name="datagram">报文</param>
    12     public TcpDatagramReceivedEventArgs(TcpClient tcpClient, T datagram)
    13     {
    14       TcpClient = tcpClient;
    15       Datagram = datagram;
    16     }
    17 
    18     /// <summary>
    19     /// 客户端
    20     /// </summary>
    21     public TcpClient TcpClient { get; private set; }
    22     /// <summary>
    23     /// 报文
    24     /// </summary>
    25     public T Datagram { get; private set; }
    26   }
    复制代码

    与服务器的连接已建立事件参数

    复制代码
     1   /// <summary>
     2   /// 与服务器的连接已建立事件参数
     3   /// </summary>
     4   public class TcpServerConnectedEventArgs : EventArgs
     5   {
     6     /// <summary>
     7     /// 与服务器的连接已建立事件参数
     8     /// </summary>
     9     /// <param name="ipAddresses">服务器IP地址列表</param>
    10     /// <param name="port">服务器端口</param>
    11     public TcpServerConnectedEventArgs(IPAddress[] ipAddresses, int port)
    12     {
    13       if (ipAddresses == null)
    14         throw new ArgumentNullException("ipAddresses");
    15 
    16       this.Addresses = ipAddresses;
    17       this.Port = port;
    18     }
    19 
    20     /// <summary>
    21     /// 服务器IP地址列表
    22     /// </summary>
    23     public IPAddress[] Addresses { get; private set; }
    24     /// <summary>
    25     /// 服务器端口
    26     /// </summary>
    27     public int Port { get; private set; }
    28 
    29     /// <summary>
    30     /// Returns a <see cref="System.String"/> that represents this instance.
    31     /// </summary>
    32     /// <returns>
    33     /// A <see cref="System.String"/> that represents this instance.
    34     /// </returns>
    35     public override string ToString()
    36     {
    37       string s = string.Empty;
    38       foreach (var item in Addresses)
    39       {
    40         s = s + item.ToString() + ',';
    41       }
    42       s = s.TrimEnd(',');
    43       s = s + ":" + Port.ToString(CultureInfo.InvariantCulture);
    44 
    45       return s;
    46     }
    47   }
    复制代码

    与服务器的连接已断开事件参数

    复制代码
     1   /// <summary>
     2   /// 与服务器的连接已断开事件参数
     3   /// </summary>
     4   public class TcpServerDisconnectedEventArgs : EventArgs
     5   {
     6     /// <summary>
     7     /// 与服务器的连接已断开事件参数
     8     /// </summary>
     9     /// <param name="ipAddresses">服务器IP地址列表</param>
    10     /// <param name="port">服务器端口</param>
    11     public TcpServerDisconnectedEventArgs(IPAddress[] ipAddresses, int port)
    12     {
    13       if (ipAddresses == null)
    14         throw new ArgumentNullException("ipAddresses");
    15 
    16       this.Addresses = ipAddresses;
    17       this.Port = port;
    18     }
    19 
    20     /// <summary>
    21     /// 服务器IP地址列表
    22     /// </summary>
    23     public IPAddress[] Addresses { get; private set; }
    24     /// <summary>
    25     /// 服务器端口
    26     /// </summary>
    27     public int Port { get; private set; }
    28 
    29     /// <summary>
    30     /// Returns a <see cref="System.String"/> that represents this instance.
    31     /// </summary>
    32     /// <returns>
    33     /// A <see cref="System.String"/> that represents this instance.
    34     /// </returns>
    35     public override string ToString()
    36     {
    37       string s = string.Empty;
    38       foreach (var item in Addresses)
    39       {
    40         s = s + item.ToString() + ',';
    41       }
    42       s = s.TrimEnd(',');
    43       s = s + ":" + Port.ToString(CultureInfo.InvariantCulture);
    44 
    45       return s;
    46     }
    47   }
    复制代码





  • 相关阅读:
    头指针与头结点的异同
    C:Users用户名AppData里面的文件可以删除吗
    mac os x在PC上安装
    迷宫问题
    对称自反传递
    判断
    离散实验模板
    离散实验二
    tp.5.0.21抛出错误
    php复制整个文件夹,此方法可过滤掉.svn文件夹
  • 原文地址:https://www.cnblogs.com/twodog/p/12137889.html
Copyright © 2011-2022 走看看