zoukankan      html  css  js  c++  java
  • 一个封装不错的 TcpClient 类

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;

    namespace RDavey.Net
    {
    public class AsyncTcpClient
    {
    private IPAddress[] addresses;
    private int port;
    private WaitHandle addressesSet;
    private TcpClient tcpClient;
    private int failedConnectionCount;

    /// <summary>
    /// Construct a new client from a known IP Address
    /// </summary>
    /// <param name="address">The IP Address of the server</param>
    /// <param name="port">The port of the server</param>
    public AsyncTcpClient(IPAddress address, int port)
    : this(new[] { address }, port)
    {
    }

    /// <summary>
    /// Construct a new client where multiple IP Addresses for
    /// the same client are known.
    /// </summary>
    /// <param name="addresses">The array of known IP Addresses</param>
    /// <param name="port">The port of the server</param>
    public AsyncTcpClient(IPAddress[] addresses, int port)
    : this(port)
    {
    this.addresses = addresses;
    }

    /// <summary>
    /// Construct a new client where the address or host name of
    /// the server is known.
    /// </summary>
    /// <param name="hostNameOrAddress">The host name or address of the server</param>
    /// <param name="port">The port of the server</param>
    public AsyncTcpClient(string hostNameOrAddress, int port)
    : this(port)
    {
    addressesSet = new AutoResetEvent(false);
    Dns.BeginGetHostAddresses(hostNameOrAddress, GetHostAddressesCallback, null);
    }

    /// <summary>
    /// Private constuctor called by other constuctors
    /// for common operations.
    /// </summary>
    /// <param name="port"></param>
    private AsyncTcpClient(int port)
    {
    if (port < 0)
    throw new ArgumentException();
    this.port = port;
    this.tcpClient = new TcpClient();
    this.Encoding = Encoding.Default;
    }

    /// <summary>
    /// The endoding used to encode/decode string when sending and receiving.
    /// </summary>
    public Encoding Encoding { get; set; }

    /// <summary>
    /// Attempts to connect to one of the specified IP Addresses
    /// </summary>
    public void Connect()
    {
    if (addressesSet != null)
    //Wait for the addresses value to be set
    addressesSet.WaitOne();
    //Set the failed connection count to 0
    Interlocked.Exchange(ref failedConnectionCount, 0);
    //Start the async connect operation
    tcpClient.BeginConnect(addresses, port, ConnectCallback, null);
    }

    /// <summary>
    /// Writes a string to the network using the defualt encoding.
    /// </summary>
    /// <param name="data">The string to write</param>
    /// <returns>A WaitHandle that can be used to detect
    /// when the write operation has completed.</returns>
    public void Write(string data)
    {
    byte[] bytes = Encoding.GetBytes(data);
    Write(bytes);
    }

    /// <summary>
    /// Writes an array of bytes to the network.
    /// </summary>
    /// <param name="bytes">The array to write</param>
    /// <returns>A WaitHandle that can be used to detect
    /// when the write operation has completed.</returns>
    public void Write(byte[] bytes)
    {
    NetworkStream networkStream = tcpClient.GetStream();
    //Start async write operation
    networkStream.BeginWrite(bytes, 0, bytes.Length, WriteCallback, null);
    }

    /// <summary>
    /// Callback for Write operation
    /// </summary>
    /// <param name="result">The AsyncResult object</param>
    private void WriteCallback(IAsyncResult result)
    {
    NetworkStream networkStream = tcpClient.GetStream();
    networkStream.EndWrite(result);
    }

    /// <summary>
    /// Callback for Connect operation
    /// </summary>
    /// <param name="result">The AsyncResult object</param>
    private void ConnectCallback(IAsyncResult result)
    {
    try
    {
    tcpClient.EndConnect(result);
    }
    catch
    {
    //Increment the failed connection count in a thread safe way
    Interlocked.Increment(ref failedConnectionCount);
    if (failedConnectionCount >= addresses.Length)
    {
    //We have failed to connect to all the IP Addresses
    //connection has failed overall.
    return;
    }
    }

    //We are connected successfully.
    NetworkStream networkStream = tcpClient.GetStream();
    byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
    //Now we are connected start asyn read operation.
    networkStream.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);
    }

    /// <summary>
    /// Callback for Read operation
    /// </summary>
    /// <param name="result">The AsyncResult object</param>
    private void ReadCallback(IAsyncResult result)
    {
    int read;
    NetworkStream networkStream;
    try
    {
    networkStream = tcpClient.GetStream();
    read = networkStream.EndRead(result);
    }
    catch
    {
    //An error has occured when reading
    return;
    }

    if (read == 0)
    {
    //The connection has been closed.
    return;
    }

    byte[] buffer = result.AsyncState as byte[];
    string data = this.Encoding.GetString(buffer, 0, read);
    //Do something with the data object here.
    //Then start reading from the network again.
    networkStream.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);
    }

    /// <summary>
    /// Callback for Get Host Addresses operation
    /// </summary>
    /// <param name="result">The AsyncResult object</param>
    private void GetHostAddressesCallback(IAsyncResult result)
    {
    addresses = Dns.EndGetHostAddresses(result);
    //Signal the addresses are now set
    ((AutoResetEvent)addressesSet).Set();
    }
    }
    }

  • 相关阅读:
    十大开源CRM
    编码转换与网址解码
    1、ADO.NET相关对象一句话介绍
    接口与抽象类对比
    C#中的文件下载问题
    在WinForm下获取粘贴板中HTML格式的数据
    Exchange学习
    用Log Explorer恢复数据的基本操作
    iframe的问题
    再发一个C#版的日历
  • 原文地址:https://www.cnblogs.com/Ken-Cai/p/4063382.html
Copyright © 2011-2022 走看看