源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

基于TCP异步Socket模型的介绍

  • 时间:2020-03-02 19:30 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:基于TCP异步Socket模型的介绍
[b]TCP异步Socket模型 [/b]C#的TCP异步Socket模型是通过Begin-End模式实现的。例如提供BeginConnect、BeginAccept、 BeginSend 和 BeginReceive等。
[u]复制代码[/u] 代码如下:
IAsyncResult BeginAccept(AsyncCallback callback, object state);
AsyncCallback回调在函数执行完毕后执行。state对象被用于在执行函数和回调函数间传输信息。
[u]复制代码[/u] 代码如下:
Socket socket = new Socket(                   AddressFamily.InterNetwork,                   SocketType.Stream,                   ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Any, 8888); socket.Bind(iep); socket.Listen(5); socket.BeginAccept (new AsyncCallback(CallbackAccept), socket); private void CallbackAccept(IAsyncResult iar) {   Socket server = (Socket)iar.AsyncState;   Socket client = server.EndAccept(iar); }
则在Accept一个TcpClient,需要维护TcpClient列表。
[u]复制代码[/u] 代码如下:
private List<TcpClientState> clients;
异步TCP服务器完整实现
[u]复制代码[/u] 代码如下:
/// <summary>    /// 异步TCP服务器    /// </summary>    public class AsyncTcpServer : IDisposable    {      #region Fields      private TcpListener listener;      private List<TcpClientState> clients;      private bool disposed = false;      #endregion      #region Ctors      /// <summary>      /// 异步TCP服务器      /// </summary>      /// <param name="listenPort">监听的端口</param>      public AsyncTcpServer(int listenPort)        : this(IPAddress.Any, listenPort)      {      }      /// <summary>      /// 异步TCP服务器      /// </summary>      /// <param name="localEP">监听的终结点</param>      public AsyncTcpServer(IPEndPoint localEP)        : this(localEP.Address, localEP.Port)      {      }      /// <summary>      /// 异步TCP服务器      /// </summary>      /// <param name="localIPAddress">监听的IP地址</param>      /// <param name="listenPort">监听的端口</param>      public AsyncTcpServer(IPAddress localIPAddress, int listenPort)      {        Address = localIPAddress;        Port = listenPort;        this.Encoding = Encoding.Default;        clients = new List<TcpClientState>();        listener = new TcpListener(Address, Port);        listener.AllowNatTraversal(true);      }      #endregion      #region Properties      /// <summary>      /// 服务器是否正在运行      /// </summary>      public bool IsRunning { get; private set; }      /// <summary>      /// 监听的IP地址      /// </summary>      public IPAddress Address { get; private set; }      /// <summary>      /// 监听的端口      /// </summary>      public int Port { get; private set; }      /// <summary>      /// 通信使用的编码      /// </summary>      public Encoding Encoding { get; set; }      #endregion      #region Server      /// <summary>      /// 启动服务器      /// </summary>      /// <returns>异步TCP服务器</returns>      public AsyncTcpServer Start()      {        if (!IsRunning)        {          IsRunning = true;          listener.Start();          listener.BeginAcceptTcpClient(            new AsyncCallback(HandleTcpClientAccepted), listener);        }        return this;      }      /// <summary>      /// 启动服务器      /// </summary>      /// <param name="backlog">      /// 服务器所允许的挂起连接序列的最大长度      /// </param>      /// <returns>异步TCP服务器</returns>      public AsyncTcpServer Start(int backlog)      {        if (!IsRunning)        {          IsRunning = true;          listener.Start(backlog);          listener.BeginAcceptTcpClient(            new AsyncCallback(HandleTcpClientAccepted), listener);        }        return this;      }      /// <summary>      /// 停止服务器      /// </summary>      /// <returns>异步TCP服务器</returns>      public AsyncTcpServer Stop()      {        if (IsRunning)        {          IsRunning = false;          listener.Stop();          lock (this.clients)          {            for (int i = 0; i < this.clients.Count; i++)            {              this.clients[i].TcpClient.Client.Disconnect(false);            }            this.clients.Clear();          }        }        return this;      }      #endregion      #region Receive      private void HandleTcpClientAccepted(IAsyncResult ar)      {        if (IsRunning)        {          TcpListener tcpListener = (TcpListener)ar.AsyncState;          TcpClient tcpClient = tcpListener.EndAcceptTcpClient(ar);          byte[] buffer = new byte[tcpClient.ReceiveBufferSize];          TcpClientState internalClient            = new TcpClientState(tcpClient, buffer);          lock (this.clients)          {            this.clients.Add(internalClient);            RaiseClientConnected(tcpClient);          }          NetworkStream networkStream = internalClient.NetworkStream;          networkStream.BeginRead(            internalClient.Buffer,            0,            internalClient.Buffer.Length,            HandleDatagramReceived,            internalClient);          tcpListener.BeginAcceptTcpClient(            new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);        }      }      private void HandleDatagramReceived(IAsyncResult ar)      {        if (IsRunning)        {          TcpClientState internalClient = (TcpClientState)ar.AsyncState;          NetworkStream networkStream = internalClient.NetworkStream;          int numberOfReadBytes = 0;          try          {            numberOfReadBytes = networkStream.EndRead(ar);          }          catch          {            numberOfReadBytes = 0;          }          if (numberOfReadBytes == 0)          {            // connection has been closed            lock (this.clients)            {              this.clients.Remove(internalClient);              RaiseClientDisconnected(internalClient.TcpClient);              return;            }          }          // received byte and trigger event notification          byte[] receivedBytes = new byte[numberOfReadBytes];          Buffer.BlockCopy(            internalClient.Buffer, 0,            receivedBytes, 0, numberOfReadBytes);          RaiseDatagramReceived(internalClient.TcpClient, receivedBytes);          RaisePlaintextReceived(internalClient.TcpClient, receivedBytes);          // continue listening for tcp datagram packets          networkStream.BeginRead(            internalClient.Buffer,            0,            internalClient.Buffer.Length,            HandleDatagramReceived,            internalClient);        }      }      #endregion      #region Events      /// <summary>      /// 接收到数据报文事件      /// </summary>      public event EventHandler<TcpDatagramReceivedEventArgs<byte[]>> DatagramReceived;      /// <summary>      /// 接收到数据报文明文事件      /// </summary>      public event EventHandler<TcpDatagramReceivedEventArgs<string>> PlaintextReceived;      private void RaiseDatagramReceived(TcpClient sender, byte[] datagram)      {        if (DatagramReceived != null)        {          DatagramReceived(this, new TcpDatagramReceivedEventArgs<byte[]>(sender, datagram));        }      }      private void RaisePlaintextReceived(TcpClient sender, byte[] datagram)      {        if (PlaintextReceived != null)        {          PlaintextReceived(this, new TcpDatagramReceivedEventArgs<string>(            sender, this.Encoding.GetString(datagram, 0, datagram.Length)));        }      }      /// <summary>      /// 与客户端的连接已建立事件      /// </summary>      public event EventHandler<TcpClientConnectedEventArgs> ClientConnected;      /// <summary>      /// 与客户端的连接已断开事件      /// </summary>      public event EventHandler<TcpClientDisconnectedEventArgs> ClientDisconnected;      private void RaiseClientConnected(TcpClient tcpClient)      {        if (ClientConnected != null)        {          ClientConnected(this, new TcpClientConnectedEventArgs(tcpClient));        }      }      private void RaiseClientDisconnected(TcpClient tcpClient)      {        if (ClientDisconnected != null)        {          ClientDisconnected(this, new TcpClientDisconnectedEventArgs(tcpClient));        }      }      #endregion      #region Send      /// <summary>      /// 发送报文至指定的客户端      /// </summary>      /// <param name="tcpClient">客户端</param>      /// <param name="datagram">报文</param>      public void Send(TcpClient tcpClient, byte[] datagram)      {        if (!IsRunning)          throw new InvalidProgramException("This TCP server has not been started.");        if (tcpClient == null)          throw new ArgumentNullException("tcpClient");        if (datagram == null)          throw new ArgumentNullException("datagram");        tcpClient.GetStream().BeginWrite(          datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);      }      private void HandleDatagramWritten(IAsyncResult ar)      {        ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);      }      /// <summary>      /// 发送报文至指定的客户端      /// </summary>      /// <param name="tcpClient">客户端</param>      /// <param name="datagram">报文</param>      public void Send(TcpClient tcpClient, string datagram)      {        Send(tcpClient, this.Encoding.GetBytes(datagram));      }      /// <summary>      /// 发送报文至所有客户端      /// </summary>      /// <param name="datagram">报文</param>      public void SendAll(byte[] datagram)      {        if (!IsRunning)          throw new InvalidProgramException("This TCP server has not been started.");        for (int i = 0; i < this.clients.Count; i++)        {          Send(this.clients[i].TcpClient, datagram);        }      }      /// <summary>      /// 发送报文至所有客户端      /// </summary>      /// <param name="datagram">报文</param>      public void SendAll(string datagram)      {        if (!IsRunning)          throw new InvalidProgramException("This TCP server has not been started.");        SendAll(this.Encoding.GetBytes(datagram));      }      #endregion      #region IDisposable Members      /// <summary>      /// Performs application-defined tasks associated with freeing,      /// releasing, or resetting unmanaged resources.      /// </summary>      public void Dispose()      {        Dispose(true);        GC.SuppressFinalize(this);      }      /// <summary>      /// Releases unmanaged and - optionally - managed resources      /// </summary>      /// <param name="disposing"><c>true</c> to release      /// both managed and unmanaged resources; <c>false</c>      /// to release only unmanaged resources.</param>      protected virtual void Dispose(bool disposing)      {        if (!this.disposed)        {          if (disposing)          {            try            {              Stop();              if (listener != null)              {                listener = null;              }            }            catch (SocketException ex)            {              ExceptionHandler.Handle(ex);            }          }          disposed = true;        }      }      #endregion    }
使用举例
[u]复制代码[/u] 代码如下:
class Program    {      static AsyncTcpServer server;      static void Main(string[] args)      {        LogFactory.Assign(new ConsoleLogFactory());        server = new AsyncTcpServer(9999);        server.Encoding = Encoding.UTF8;        server.ClientConnected +=          new EventHandler<TcpClientConnectedEventArgs>(server_ClientConnected);        server.ClientDisconnected +=          new EventHandler<TcpClientDisconnectedEventArgs>(server_ClientDisconnected);        server.PlaintextReceived +=          new EventHandler<TcpDatagramReceivedEventArgs<string>>(server_PlaintextReceived);        server.Start();        Console.WriteLine("TCP server has been started.");        Console.WriteLine("Type something to send to client...");        while (true)        {          string text = Console.ReadLine();          server.SendAll(text);        }      }      static void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)      {        Logger.Debug(string.Format(CultureInfo.InvariantCulture,          "TCP client {0} has connected.",          e.TcpClient.Client.RemoteEndPoint.ToString()));      }      static void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)      {        Logger.Debug(string.Format(CultureInfo.InvariantCulture,          "TCP client {0} has disconnected.",          e.TcpClient.Client.RemoteEndPoint.ToString()));      }      static void server_PlaintextReceived(object sender, TcpDatagramReceivedEventArgs<string> e)      {        if (e.Datagram != "Received")        {          Console.Write(string.Format("Client : {0} --> ",            e.TcpClient.Client.RemoteEndPoint.ToString()));          Console.WriteLine(string.Format("{0}", e.Datagram));          server.Send(e.TcpClient, "Server has received you text : " + e.Datagram);        }      }    }
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部