using DyeingComputer.UserClass; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Reflection.Emit; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; namespace DyeingComputer.UserClass {/// /// 异步TCP服务器 /// public class AsyncTcpServer : IDisposable { #region Fields private TcpListener listener; private List clients; private bool disposed = false; #endregion #region Ctors /// /// 异步TCP服务器 /// /// 监听的端口 public AsyncTcpServer(int listenPort) : this(IPAddress.Any, listenPort) { } /// /// 异步TCP服务器 /// /// 监听的终结点 public AsyncTcpServer(IPEndPoint localEP) : this(localEP.Address, localEP.Port) { } /// /// 异步TCP服务器 /// /// 监听的IP地址 /// 监听的端口 public AsyncTcpServer(IPAddress localIPAddress, int listenPort) { Address = localIPAddress; Port = listenPort; this.Encoding = Encoding.Default; clients = new List(); listener = new TcpListener(Address, Port); listener.AllowNatTraversal(true); } #endregion #region Properties /// /// 服务器是否正在运行 /// public bool IsRunning { get; private set; } /// /// 监听的IP地址 /// public IPAddress Address { get; private set; } /// /// 监听的端口 /// public int Port { get; private set; } /// /// 通信使用的编码 /// public Encoding Encoding { get; set; } #endregion #region Server /// /// 启动服务器 /// /// 异步TCP服务器 public AsyncTcpServer Start() { if (!IsRunning) { IsRunning = true; listener.Start(); listener.BeginAcceptTcpClient( new AsyncCallback(HandleTcpClientAccepted), listener); } return this; } /// /// 启动服务器 /// /// /// 服务器所允许的挂起连接序列的最大长度 /// /// 异步TCP服务器 public AsyncTcpServer Start(int backlog) { if (!IsRunning) { IsRunning = true; listener.Start(backlog); listener.BeginAcceptTcpClient( new AsyncCallback(HandleTcpClientAccepted), listener); } return this; } /// /// 停止服务器 /// /// 异步TCP服务器 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 /// /// 接收到数据报文事件 /// public event EventHandler> DatagramReceived; /// /// 接收到数据报文明文事件 /// public event EventHandler> PlaintextReceived; private void RaiseDatagramReceived(TcpClient sender, byte[] datagram) { if (DatagramReceived != null) { DatagramReceived(this, new TcpDatagramReceivedEventArgs(sender, datagram)); } } private void RaisePlaintextReceived(TcpClient sender, byte[] datagram) { if (PlaintextReceived != null) { PlaintextReceived(this, new TcpDatagramReceivedEventArgs( sender, this.Encoding.GetString(datagram, 0, datagram.Length))); } } /// /// 与客户端的连接已建立事件 /// public event EventHandler ClientConnected; /// /// 与客户端的连接已断开事件 /// public event EventHandler 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 /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 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); } /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 public void Send(TcpClient tcpClient, string datagram) { Send(tcpClient, this.Encoding.GetBytes(datagram)); } /// /// 发送报文至所有客户端 /// /// 报文 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); } } /// /// 发送报文至所有客户端 /// /// 报文 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 /// /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Releases unmanaged and - optionally - managed resources /// /// true to release /// both managed and unmanaged resources; false /// to release only unmanaged resources. 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 } }