diff --git a/DyeingComputer.csproj b/DyeingComputer.csproj index b945504..5303790 100644 --- a/DyeingComputer.csproj +++ b/DyeingComputer.csproj @@ -143,7 +143,7 @@ - + @@ -348,7 +348,7 @@ 2.0.7 - 8.2.2 + 8.3.2 2.0.0-rc3.3 @@ -366,7 +366,7 @@ 3.0.81 - 5.0.37 + 5.0.39 4.5.1 @@ -375,7 +375,7 @@ 5.0.0 - 1.0.118 + 1.0.119 4.5.5 @@ -389,6 +389,9 @@ 4.5.4 + + 2.1.9 + diff --git a/UserClass/AsyncTcpServer.cs b/UserClass/AsyncTcpServer.cs new file mode 100644 index 0000000..4032fea --- /dev/null +++ b/UserClass/AsyncTcpServer.cs @@ -0,0 +1,404 @@ +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 + } +} + + + + + + diff --git a/UserClass/TCPServer.cs b/UserClass/TCPServer.cs deleted file mode 100644 index 697b0f1..0000000 --- a/UserClass/TCPServer.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -namespace DyeingComputer.UserClass -{ - public class TCPServer - { - public static string infoR; - //第一步:调用socket()函数创建一个用于通信的套接字 - public static Socket listenSocket; - - //字典集合:存储IP和Socket的集合 - public static Dictionary OnLineList = new Dictionary(); - - - //当前时间 - private string CurrentTime - { - get { return DateTime.Now.ToString("HH:mm:ss") + Environment.NewLine; } - } - - //编码格式 - public static Encoding econding = Encoding.UTF8; - - public static void Start() - { - //第一步:调用socket()函数创建一个用于通信的套接字 - listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - //第二步:给已经创建的套接字绑定一个端口号,这一般通过设置网络套接口地址和调用Bind()函数来实现 - IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(UserClass.get_local_ip_address.IP_Address()), int.Parse("11080")); - UserClass.LogGing.LogGingDATA("NativeIP = " + UserClass.get_local_ip_address.IP_Address()); - UserClass.LogGing.LogGingDATA("NativePORT = 11080"); - try - { - listenSocket.Bind(endPoint); - } - catch (Exception ex) - { - UserClass.LogGing.LogGingDATA("TCP_NotStart"); - UserClass.LogGing.LogGingDATA(ex.Message); - return; - } - //第三步:调用listen()函数使套接字成为一个监听套接字 - listenSocket.Listen(10); - //ShowMessage("服务器开启成功"); - - //开启一个线程监听 - Task.Run(new Action(() => { ListenConnection(); })); - } - - public static void ListenConnection() - { - while (true) - { - Socket clientSocket = listenSocket.Accept(); - string ip = clientSocket.RemoteEndPoint.ToString(); - //更新在线列表 - // AddOnLine(ip, true); - //更新在线列表集合 - OnLineList.Add(ip, clientSocket); - UserClass.LogGing.LogGingDATA("IP_Online = " + ip); - // ShowMessage(ip + "上线了"); - Task.Run(() => ReceiveMsg(clientSocket)); - } - } - - /// - /// 接收方法 - /// - /// - public static void ReceiveMsg(Socket clientSocket) - { - while (true) - { - //定义一个2M的缓冲区 - byte[] buffer = new byte[1024 * 1024 * 10]; - - int length = -1; - try - { - length = clientSocket.Receive(buffer); - } - catch (Exception) - { - //客户端下线了 - //更新在线列表 - string ip = clientSocket.RemoteEndPoint.ToString(); - UserClass.LogGing.LogGingDATA("IP_Line = " + ip); - // AddOnLine(ip, false); - OnLineList.Remove(ip); //移除ip - break; //退出循环 - } - - if (length == 0) - { - //客户端下线了 - //更新在线列表 - string ip = clientSocket.RemoteEndPoint.ToString(); - UserClass.LogGing.LogGingDATA("IP_Line = " + ip); - // AddOnLine(ip, false); - OnLineList.Remove(ip); - break; - } - else - { - infoR = econding.GetString(buffer, 0, length); - //ShowMessage(info); - string ip = clientSocket.RemoteEndPoint.ToString(); - } - } - - } - /* - /// - /// 在线列表更新 - /// - /// - /// - private void AddOnLine(string clientIp, bool value) - { - Invoke(new Action(() => - { - if (value) - { - this.lst_Online.Items.Add(clientIp); - } - else - { - this.lst_Online.Items.Remove(clientIp); - } - - })); - - } - - - /// - /// 更新接收区 - /// - /// - private void ShowMessage(string info) - { - Invoke(new Action(() => - { - this.txt_Rcv.AppendText(CurrentTime + info + Environment.NewLine); - })); - - } - - */ - /// - /// 消息发送 - /// - public static void Bn_Send(string IP, string DAT) - { - if (OnLineList.ContainsKey(IP)) - { - OnLineList[IP].Send(econding.GetBytes(DAT)); - } - } - - /// - /// 群发功能 - /// - public static void Btn_SendAll(string DAT) - { - foreach (string item in OnLineList.Keys.ToArray()) - { - if (OnLineList.ContainsKey(item)) - { - OnLineList[item].Send(econding.GetBytes(DAT)); - } - } - } - - } -} - - -