From 938f7f1ca20b691c3c42c2a5402374ee8d140226 Mon Sep 17 00:00:00 2001 From: SpringHgui <740360381@qq.com> Date: Sun, 28 Jun 2020 23:39:05 +0800 Subject: [PATCH] add Listener interface --- FastTunnel.Core/AsyncListener.cs | 162 ++++++++++++++++++ FastTunnel.Core/Core/SuiDaoServer.cs | 8 +- .../Handlers/Server/LoginHandler.cs | 21 ++- FastTunnel.Core/IListener.cs | 12 ++ FastTunnel.Core/Listener.cs | 11 +- 5 files changed, 193 insertions(+), 21 deletions(-) create mode 100644 FastTunnel.Core/AsyncListener.cs create mode 100644 FastTunnel.Core/IListener.cs diff --git a/FastTunnel.Core/AsyncListener.cs b/FastTunnel.Core/AsyncListener.cs new file mode 100644 index 0000000..e81629c --- /dev/null +++ b/FastTunnel.Core/AsyncListener.cs @@ -0,0 +1,162 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core +{ + public class AsyncListener : IListener + { + ILogger _logerr; + + public string IP { get; set; } + + public int Port { get; set; } + + Action handler; + Socket listener; + T _data; + + public AsyncListener(string ip, int port, ILogger logerr, T data) + { + _logerr = logerr; + _data = data; + this.IP = ip; + this.Port = port; + + IPAddress ipa = IPAddress.Parse(IP); + IPEndPoint localEndPoint = new IPEndPoint(ipa, Port); + + listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + listener.Bind(localEndPoint); + } + + public void Listen(Action receiveClient) + { + // example https://docs.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example + // Bind the socket to the local endpoint and listen for incoming connections. + try + { + listener.Listen(100); + + while (true) + { + // Set the event to nonsignaled state. + //allDone.Reset(); + + // Start an asynchronous socket to listen for connections. + Console.WriteLine("Waiting for a connection..."); + listener.BeginAccept( + new AsyncCallback(AcceptCallback), + listener); + + // Wait until a connection is made before continuing. + //allDone.WaitOne(); + } + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + + void AcceptCallback(IAsyncResult ar) + { + // Signal the main thread to continue. + //allDone.Set(); + + // Get the socket that handles the client request. + Socket listener = (Socket)ar.AsyncState; + Socket handler = listener.EndAccept(ar); + + // Create the state object. + StateObject state = new StateObject(); + state.workSocket = handler; + handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); + } + + void ReadCallback(IAsyncResult ar) + { + String content = String.Empty; + + // Retrieve the state object and the handler socket + // from the asynchronous state object. + StateObject state = (StateObject)ar.AsyncState; + Socket handler = state.workSocket; + + // Read data from the client socket. + int bytesRead = handler.EndReceive(ar); + + if (bytesRead > 0) + { + // There might be more data, so store the data received so far. + state.sb.Append(Encoding.ASCII.GetString( + state.buffer, 0, bytesRead)); + + // Check for end-of-file tag. If it is not there, read + // more data. + content = state.sb.ToString(); + if (content.IndexOf("") > -1) + { + // All the data has been read from the + // client. Display it on the console. + Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", + content.Length, content); + // Echo the data back to the client. + Send(handler, content); + } + else + { + // Not all data received. Get more. + handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); + } + } + } + + void Send(Socket handler, String data) + { + // Convert the string data to byte data using ASCII encoding. + byte[] byteData = Encoding.ASCII.GetBytes(data); + + // Begin sending the data to the remote device. + handler.BeginSend(byteData, 0, byteData.Length, 0, + new AsyncCallback(SendCallback), handler); + } + + void SendCallback(IAsyncResult ar) + { + try + { + // Retrieve the socket from the state object. + Socket handler = (Socket)ar.AsyncState; + + // Complete sending the data to the remote device. + int bytesSent = handler.EndSend(ar); + Console.WriteLine("Sent {0} bytes to client.", bytesSent); + + handler.Shutdown(SocketShutdown.Both); + handler.Close(); + + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + } + + public class StateObject + { + // Client socket. + public Socket workSocket = null; + // Size of receive buffer. + public const int BufferSize = 1024; + // Receive buffer. + public byte[] buffer = new byte[BufferSize]; + // Received data string. + public StringBuilder sb = new StringBuilder(); + } +} diff --git a/FastTunnel.Core/Core/SuiDaoServer.cs b/FastTunnel.Core/Core/SuiDaoServer.cs index 1111f80..6082f2d 100644 --- a/FastTunnel.Core/Core/SuiDaoServer.cs +++ b/FastTunnel.Core/Core/SuiDaoServer.cs @@ -51,15 +51,15 @@ namespace FastTunnel.Core.Core private void ListenFastTunnelClient() { - var listener = new Listener(_serverSettings.BindAddr, _serverSettings.BindPort, _logger, ReceiveClient, null); - listener.Listen(); + IListener listener = new Listener(_serverSettings.BindAddr, _serverSettings.BindPort, _logger, null); + listener.Listen(ReceiveClient); _logger.LogDebug($"监听客户端 -> {_serverSettings.BindAddr}:{_serverSettings.BindPort}"); } private void ListenCustomer() { - var listener = new Listener(_serverSettings.BindAddr, _serverSettings.ProxyPort_HTTP, _logger, ReceiveCustomer, null); - listener.Listen(); + var listener = new Listener(_serverSettings.BindAddr, _serverSettings.ProxyPort_HTTP, _logger, null); + listener.Listen(ReceiveCustomer); _logger.LogDebug($"监听HTTP -> {_serverSettings.BindAddr}:{_serverSettings.ProxyPort_HTTP}"); } diff --git a/FastTunnel.Core/Handlers/Server/LoginHandler.cs b/FastTunnel.Core/Handlers/Server/LoginHandler.cs index 69606df..c5e0dc1 100644 --- a/FastTunnel.Core/Handlers/Server/LoginHandler.cs +++ b/FastTunnel.Core/Handlers/Server/LoginHandler.cs @@ -93,18 +93,17 @@ namespace FastTunnel.Core.Handlers var ls = new Listener("0.0.0.0", item.RemotePort, _logger, - (client, local) => - { - var msgid = Guid.NewGuid().ToString(); - local.LocalClient.Send(new Message { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = local.SSHConfig } }); + new SSHHandlerArg { LocalClient = client, SSHConfig = item }); + ls.Listen((client, local) => + { + var msgid = Guid.NewGuid().ToString(); + local.LocalClient.Send(new Message { MessageType = MessageType.S_NewSSH, Content = new NewSSHRequest { MsgId = msgid, SSHConfig = local.SSHConfig } }); - server.newRequest.Add(msgid, new NewRequest - { - CustomerClient = client, - }); - } - , new SSHHandlerArg { LocalClient = client, SSHConfig = item }); - ls.Listen(); + server.newRequest.Add(msgid, new NewRequest + { + CustomerClient = client, + }); + }); // listen success server.SSHList.Add(item.RemotePort, new SSHInfo { Listener = ls, Socket = client, SSHConfig = item }); diff --git a/FastTunnel.Core/IListener.cs b/FastTunnel.Core/IListener.cs new file mode 100644 index 0000000..bf3df92 --- /dev/null +++ b/FastTunnel.Core/IListener.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; + +namespace FastTunnel.Core +{ + public interface IListener + { + void Listen(Action receiveClient); + } +} diff --git a/FastTunnel.Core/Listener.cs b/FastTunnel.Core/Listener.cs index e6f1fcd..612cb65 100644 --- a/FastTunnel.Core/Listener.cs +++ b/FastTunnel.Core/Listener.cs @@ -9,7 +9,8 @@ using FastTunnel.Core.Extensions; namespace FastTunnel.Core { - public class Listener + [Obsolete("Replaced by AsyncListener")] + public class Listener : IListener { ILogger _logerr; @@ -21,14 +22,12 @@ namespace FastTunnel.Core Socket ls; T _data; - - public Listener(string ip, int port, ILogger logerr, Action acceptCustomerHandler, T data) + public Listener(string ip, int port, ILogger logerr, T data) { _logerr = logerr; _data = data; this.IP = ip; this.Port = port; - handler = acceptCustomerHandler; IPAddress ipa = IPAddress.Parse(IP); IPEndPoint ipe = new IPEndPoint(ipa, Port); @@ -37,8 +36,9 @@ namespace FastTunnel.Core ls.Bind(ipe); } - public void Listen() + public void Listen(Action receiveClient) { + this.handler = receiveClient; ls.Listen(100); ThreadPool.QueueUserWorkItem((state) => { @@ -63,7 +63,6 @@ namespace FastTunnel.Core throw; } } - }, ls); }