using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; namespace JiLinApp.Docking.VibrateAlarm; public class AsyncTcpServer : IDisposable { #region Fields private TcpListener _listener; private ConcurrentDictionary _clients; private bool _disposed = false; #endregion Fields #region Ctors private byte[] inOptionValues; /// /// 异步TCP服务器 /// /// 监听的端口 public AsyncTcpServer(int listenPort) : this(IPAddress.Any, listenPort) { uint dummy = 0; inOptionValues = new byte[Marshal.SizeOf(dummy) * 3]; BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy)); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2); } /// /// 异步TCP服务器 /// /// 监听的终结点 public AsyncTcpServer(IPEndPoint localEP) : this(localEP.Address, localEP.Port) { uint dummy = 0; inOptionValues = new byte[Marshal.SizeOf(dummy) * 3]; BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy)); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2); } /// /// 异步TCP服务器 /// /// 监听的IP地址 /// 监听的端口 public AsyncTcpServer(IPAddress localIPAddress, int listenPort) { uint dummy = 0; inOptionValues = new byte[Marshal.SizeOf(dummy) * 3]; BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy)); BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2); Address = localIPAddress; Port = listenPort; Encoding = Encoding.Default; _clients = new ConcurrentDictionary(); _listener = new TcpListener(Address, Port); _listener.AllowNatTraversal(true); } #endregion Ctors #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 Properties #region Server /// /// 启动服务器 /// /// 异步TCP服务器 public AsyncTcpServer Start() { return Start(30); } /// /// 启动服务器 /// /// 服务器所允许的挂起连接序列的最大长度 /// 异步TCP服务器 public AsyncTcpServer Start(int backlog) { if (IsRunning) return this; IsRunning = true; _listener.Start(backlog); ContinueAcceptTcpClient(_listener); return this; } /// /// 停止服务器 /// /// 异步TCP服务器 public AsyncTcpServer Stop() { if (!IsRunning) return this; try { _listener.Stop(); foreach (var client in _clients.Values) { client.TcpClient.Client.Disconnect(false); } _clients.Clear(); } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } catch (SocketException ex) { Console.WriteLine("socket错误:" + ex.Message); } IsRunning = false; return this; } private void ContinueAcceptTcpClient(TcpListener tcpListener) { try { tcpListener.BeginAcceptTcpClient(new AsyncCallback(HandleTcpClientAccepted), tcpListener); } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } catch (SocketException ex) { Console.WriteLine("socket错误:" + ex.Message); } } #endregion Server #region Receive private void HandleTcpClientAccepted(IAsyncResult ar) { if (!IsRunning) return; TcpListener tcpListener; TcpClient tcpClient; try { tcpListener = (TcpListener)ar.AsyncState; tcpClient = tcpListener.EndAcceptTcpClient(ar); tcpClient.Client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null); } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); return; } if (!tcpClient.Connected) return; byte[] buffer = new byte[tcpClient.ReceiveBufferSize]; TcpClientState internalClient = new TcpClientState(tcpClient, buffer); // add client connection to cache string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString(); _clients.AddOrUpdate(tcpClientKey, internalClient, (n, o) => { return internalClient; }); RaiseClientConnected(tcpClient); // begin to read data NetworkStream networkStream = internalClient.NetworkStream; ContinueReadBuffer(internalClient, networkStream); // keep listening to accept next connection ContinueAcceptTcpClient(tcpListener); } private void HandleDatagramReceived(IAsyncResult ar) { if (!IsRunning) return; try { TcpClientState internalClient = (TcpClientState)ar.AsyncState; if (!internalClient.TcpClient.Connected) return; NetworkStream networkStream = internalClient.NetworkStream; int numberOfReadBytes = 0; try { // if the remote host has shutdown its connection, // read will immediately return with zero bytes. numberOfReadBytes = networkStream.EndRead(ar); } catch (Exception ex) { Console.WriteLine("错误:" + ex.Message); numberOfReadBytes = 0; } if (numberOfReadBytes == 0) { // connection has been closed TcpClientState internalClientToBeThrowAway; string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString(); _clients.TryRemove(tcpClientKey, out internalClientToBeThrowAway); 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, receivedBytes); // continue listening for tcp datagram packets ContinueReadBuffer(internalClient, networkStream); } catch (InvalidOperationException ex) { Console.WriteLine("错误:" + ex.Message); } } private void ContinueReadBuffer(TcpClientState internalClient, NetworkStream networkStream) { try { networkStream.BeginRead(internalClient.Buffer, 0, internalClient.Buffer.Length, HandleDatagramReceived, internalClient); } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } } #endregion Receive #region Events /// /// 接收到数据报文事件 /// public event EventHandler> DatagramReceived; private void RaiseDatagramReceived(TcpClientState sender, byte[] datagram) { if (DatagramReceived != null) { DatagramReceived(this, new TcpDatagramReceivedEventArgs(sender, datagram)); } } /// /// 与客户端的连接已建立事件 /// 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 Events #region Send private void GuardRunning() { if (!IsRunning) throw new InvalidProgramException("This TCP server has not been started yet."); } /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 public void Send(TcpClient tcpClient, byte[] datagram) { GuardRunning(); if (tcpClient == null) throw new ArgumentNullException("tcpClient"); if (datagram == null) throw new ArgumentNullException("datagram"); try { NetworkStream stream = tcpClient.GetStream(); if (stream.CanWrite) { stream.BeginWrite(datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient); } } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } } /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 public void Send(TcpClient tcpClient, string datagram) { Send(tcpClient, Encoding.GetBytes(datagram)); } /// /// 发送报文至所有客户端 /// /// 报文 public void SendToAll(byte[] datagram) { GuardRunning(); foreach (var client in _clients.Values) { Send(client.TcpClient, datagram); } } public ICollection GetAllClient() { return _clients.Values; } /// /// 发送报文至所有客户端 /// /// 报文 public void SendToAll(string datagram) { GuardRunning(); SendToAll(Encoding.GetBytes(datagram)); } private void HandleDatagramWritten(IAsyncResult ar) { try { ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar); } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } catch (InvalidOperationException ex) { Console.WriteLine("错误:" + ex.Message); } catch (IOException ex) { Console.WriteLine("错误:" + ex.Message); } } /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 public void SyncSend(TcpClient tcpClient, byte[] datagram) { GuardRunning(); if (tcpClient == null) throw new ArgumentNullException("tcpClient"); if (datagram == null) throw new ArgumentNullException("datagram"); try { NetworkStream stream = tcpClient.GetStream(); if (stream.CanWrite) { stream.Write(datagram, 0, datagram.Length); } } catch (ObjectDisposedException ex) { Console.WriteLine("对象注销错误:" + ex.Message); } } /// /// 发送报文至指定的客户端 /// /// 客户端 /// 报文 public void SyncSend(TcpClient tcpClient, string datagram) { SyncSend(tcpClient, Encoding.GetBytes(datagram)); } /// /// 发送报文至所有客户端 /// /// 报文 public void SyncSendToAll(byte[] datagram) { GuardRunning(); foreach (var client in _clients.Values) { SyncSend(client.TcpClient, datagram); } } /// /// 发送报文至所有客户端 /// /// 报文 public void SyncSendToAll(string datagram) { GuardRunning(); SyncSendToAll(Encoding.GetBytes(datagram)); } #endregion Send #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 (!_disposed) { if (disposing) { try { Stop(); if (_listener != null) { _listener = null; } } catch (SocketException ex) { Console.WriteLine("socket错误:" + ex.Message); } } _disposed = true; } } #endregion IDisposable Members }