From 135a40c1178abd448d1344789368958ee8bf156c Mon Sep 17 00:00:00 2001 From: tmoonlight Date: Wed, 13 Feb 2019 14:03:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AB=AF=E5=8F=A3=E5=A4=8D?= =?UTF-8?q?=E7=94=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NSmartProxy.Client/ClientAppWorker.cs | 14 ++ .../NSmartProxy.Client/ClientRouter.cs | 16 +- .../NSmartProxy.ClientServer.csproj | 4 + .../ServerConnnectionManager.cs | 61 +++--- .../NSmartProxy.Client/Util/StringUtil.cs | 52 ++--- NSmartProxy/NSmartProxy.Data/Model.cs | 67 +++++- NSmartProxy/NSmartProxy.Data/StringUtil.cs | 18 +- .../NSmartProxy.Test/NSmartProxy.Test.csproj | 3 +- NSmartProxy/NSmartProxy.Test/Program.cs | 195 +++--------------- .../NSmartProxy.Test/Program_client.cs | 34 +-- .../NSmartProxy/ClientConnectionManager.cs | 124 +++++++---- NSmartProxy/NSmartProxy/NSmartProxy.csproj | 4 + NSmartProxy/NSmartProxy/Server.cs | 15 +- 13 files changed, 302 insertions(+), 305 deletions(-) create mode 100644 NSmartProxy/NSmartProxy.Client/ClientAppWorker.cs diff --git a/NSmartProxy/NSmartProxy.Client/ClientAppWorker.cs b/NSmartProxy/NSmartProxy.Client/ClientAppWorker.cs new file mode 100644 index 0000000..a83450c --- /dev/null +++ b/NSmartProxy/NSmartProxy.Client/ClientAppWorker.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; + +namespace NSmartProxy +{ + public class ClientAppWorker + { + public List TcpClientGroup = new List(); + public int AppId; //1~255 + public int Port; //0~65535 + } +} diff --git a/NSmartProxy/NSmartProxy.Client/ClientRouter.cs b/NSmartProxy/NSmartProxy.Client/ClientRouter.cs index 95c8fd8..58304c6 100644 --- a/NSmartProxy/NSmartProxy.Client/ClientRouter.cs +++ b/NSmartProxy/NSmartProxy.Client/ClientRouter.cs @@ -21,7 +21,8 @@ public class ClientRouter CancellationTokenSource CANCELTOKEN = new CancellationTokenSource(); CancellationTokenSource TRANSFERING_TOKEN = new CancellationTokenSource(); ServerConnnectionManager ConnnectionManager; - + public Dictionary AppPortMap; //key:appid,value:servicetargetport 目标端口 + /// /// 重要:连接服务端 /// @@ -39,20 +40,21 @@ private void ServerConnnectionManager_ClientGroupConnected(object sender, EventA { Console.WriteLine("开启连接"); - OpenTrasferation(providerClient); + OpenTrasferation(args.App.AppId, providerClient); } } - private async Task OpenTrasferation(TcpClient providerClient) + private async Task OpenTrasferation(int appId, TcpClient providerClient) { byte[] buffer = new byte[4096]; var providerClientStream = providerClient.GetStream(); int readByteCount = await providerClientStream.ReadAsync(buffer); //从空闲连接列表中移除 - ConnnectionManager.RemoveClient(providerClient); - Console.WriteLine("接受到首条信息"); + ConnnectionManager.RemoveClient(appId, providerClient); + Console.WriteLine(appId + "接受到首条信息"); TcpClient toTargetServer = new TcpClient(); + //※根据clientid_appid发送到固定的端口※ toTargetServer.Connect(TARGET_SERVICE_ADDRESS, TARGET_SERVICE_ADDRESS_PORT); NetworkStream targetServerStream = toTargetServer.GetStream(); targetServerStream.Write(buffer, 0, readByteCount); @@ -77,14 +79,14 @@ private async Task TcpTransferAsync(NetworkStream providerStream, NetworkStream } - + private async Task StreamTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func> beforeTransfer = null) { await fromStream.CopyToAsync(toStream, ct); return signal; } - + private async Task ToStaticTransfer(CancellationToken ct, NetworkStream fromStream, NetworkStream toStream, string signal, Func> beforeTransfer = null) { diff --git a/NSmartProxy/NSmartProxy.Client/NSmartProxy.ClientServer.csproj b/NSmartProxy/NSmartProxy.Client/NSmartProxy.ClientServer.csproj index 23df604..eb8dda3 100644 --- a/NSmartProxy/NSmartProxy.Client/NSmartProxy.ClientServer.csproj +++ b/NSmartProxy/NSmartProxy.Client/NSmartProxy.ClientServer.csproj @@ -5,4 +5,8 @@ netcoreapp2.1 + + + + diff --git a/NSmartProxy/NSmartProxy.Client/ServerConnnectionManager.cs b/NSmartProxy/NSmartProxy.Client/ServerConnnectionManager.cs index 73d28ea..b483a8f 100644 --- a/NSmartProxy/NSmartProxy.Client/ServerConnnectionManager.cs +++ b/NSmartProxy/NSmartProxy.Client/ServerConnnectionManager.cs @@ -1,4 +1,5 @@ using NSmartProxy.Client; +using NSmartProxy.Data; using System; using System.Collections.Generic; using System.Net; @@ -11,6 +12,7 @@ namespace NSmartProxy public class ClientGroupEventArgs : EventArgs { public IEnumerable NewClients; + public ClientIdAppId App; } public class ServerConnnectionManager @@ -23,18 +25,22 @@ private ServerConnnectionManager() //获取服务端配置信息 //测试 ,暂时设置为3 //int length = Apps.Length - byte[] configBytes = ReadConfigFromProvider(); - //※要求服务端分配资源并获取服务端配置※,待完善 + ClientModel clientModel = ReadConfigFromProvider(); + //要求服务端分配资源并获取服务端配置,待完善 //Console.WriteLine(config[0] + "!!!!!!!!!"); //唯一的clientid - ClientID = configBytes[0] << 8 + configBytes[1]; + this.ClientID = clientModel.ClientId; //分配appid - ServiceClientListCollection = new Dictionary>(); - for (int i = 2; i < configBytes.Length; i++) + ServiceClientListCollection = new Dictionary(); + for (int i = 0; i < clientModel.AppList.Count; i++) { - if (configBytes[i] == 0) - break; - ServiceClientListCollection.Add((int)configBytes[i], new List()); + var app = clientModel.AppList[i]; + ServiceClientListCollection.Add(clientModel.AppList[i].AppId, new ClientAppWorker() + { + AppId = app.AppId, + Port = app.Port, + TcpClientGroup = new List(MAX_CONNECT_SIZE) + }); } //arrangedAppid = configBytes[] @@ -45,16 +51,17 @@ private ServerConnnectionManager() /// 从服务端读取配置 /// /// - private static byte[] ReadConfigFromProvider() + private static ClientModel ReadConfigFromProvider() { TcpClient configClient = new TcpClient(); configClient.Connect(ClientRouter.PROVIDER_ADDRESS, ClientRouter.PROVIDER_CONFIG_SERVICE_PORT); var configStream = configClient.GetStream(); - byte[] fourBytes = new byte[4] { 0, 0, 3, 0 }; - configStream.Write(fourBytes); + + //byte[] fourBytes = new byte[4] { 0, 0, 3, 0 }; + configStream.Write(new ClientNewAppRequest { ClientId = 0, ClientCount = 3 }.ToBytes()); byte[] config = new byte[256]; - configStream.Read(config); - return config; + int readBytesCount = configStream.Read(config); + return ClientModel.GetFromBytes(config, readBytesCount); } public static event EventHandler ClientGroupConnected; @@ -62,7 +69,7 @@ private async Task PollingToProvider() { if (ClientID == 0) { Console.WriteLine("error:未连接客户端"); return; }; int hungryNumber = MAX_CONNECT_SIZE / 2; - byte[] clientBytes = StringUtil.IntToBytes(ClientID); + byte[] clientBytes = StringUtil.IntTo2Bytes(ClientID); //侦听,并且构造连接池 //throw new NotImplementedException(); //int currentClientCount = ServiceClientQueue.Count; @@ -70,14 +77,15 @@ private async Task PollingToProvider() foreach (var kv in ServiceClientListCollection) { int appid = kv.Key; - byte[] requestBytes = StringUtil.Generate1stRequestBytes(ClientID,appid); + ClientAppWorker app = kv.Value; + byte[] requestBytes = StringUtil.ClientIDAppIdToBytes(ClientID, appid); taskList.Add(Task.Run(async () => { while (1 == 1) { int activeClientCount = 0; - foreach (TcpClient c in ServiceClientListCollection[appid]) + foreach (TcpClient c in app.TcpClientGroup) { if (c.Connected) activeClientCount++; } @@ -93,10 +101,13 @@ private async Task PollingToProvider() client.Connect(ClientRouter.PROVIDER_ADDRESS, ClientRouter.PROVIDER_ADDRESS_PORT); //连完了马上发送端口信息过去,方便服务端分配 client.GetStream().Write(requestBytes); - ServiceClientListCollection[appid].Add(client); + app.TcpClientGroup.Add(client); clientList.Add(client); } - ClientGroupConnected(this, new ClientGroupEventArgs() { NewClients = clientList }); + ClientGroupConnected(this, new ClientGroupEventArgs() { + NewClients = clientList, + App = new ClientIdAppId { ClientId = ClientID, AppId = appid + } }); } await Task.Delay(2000); //currentClientCount = ServiceClientQueue.Count; @@ -108,14 +119,14 @@ private async Task PollingToProvider() Console.WriteLine(resultTask.Exception?.ToString()); } - //可能要改成字典 - private Dictionary> ServiceClientListCollection;// = new Dictionary>(); + //key:appid value;ClientApp + private Dictionary ServiceClientListCollection;// = new Dictionary>(); private static ServerConnnectionManager Instance = new Lazy(() => new ServerConnnectionManager()).Value; //Queue IdleClientsQueue = new Queue(); - public void AddClient(int appId, TcpClient client) - { - ServiceClientListCollection[appId].Add(client); - } + //public void AddClient(int appId, TcpClient client) + //{ + // ServiceClientListCollection[appId].Add(client); + //} public static ServerConnnectionManager GetInstance() { @@ -124,7 +135,7 @@ public static ServerConnnectionManager GetInstance() public TcpClient RemoveClient(int appId, TcpClient client) { - if (ServiceClientListCollection[appId].Remove(client)) + if (ServiceClientListCollection[appId].TcpClientGroup.Remove(client)) return client; else diff --git a/NSmartProxy/NSmartProxy.Client/Util/StringUtil.cs b/NSmartProxy/NSmartProxy.Client/Util/StringUtil.cs index bd3441c..d618661 100644 --- a/NSmartProxy/NSmartProxy.Client/Util/StringUtil.cs +++ b/NSmartProxy/NSmartProxy.Client/Util/StringUtil.cs @@ -1,28 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Text; +//using System; +//using System.Collections.Generic; +//using System.Text; -namespace NSmartProxy -{ - public class StringUtil - { - public static byte[] IntToBytes(int number) - { - return System.BitConverter.GetBytes(number); - } +//namespace NSmartProxy +//{ +// public class StringUtil +// { +// public static byte[] IntTo222Bytes(int number) +// { +// return System.BitConverter.GetBytes(number); +// } - /// - /// 客户端首次连接服务端时,需要发送标记以便服务端归类 - /// - /// - /// - /// - public static byte[] Generate1stRequestBytes(int clientID, int appid) - { - byte[] bytes = IntToBytes(clientID); - bytes[2] = (byte)appid; - bytes[3] = 0; - return bytes; - } - } -} +// /// +// /// 客户端首次连接服务端时,需要发送标记以便服务端归类 +// /// +// /// +// /// +// /// +// public static byte[] Generate1stRe为questBytes(int clientID, int appid) +// { +// byte[] bytes = IntToBytes(clientID); +// bytes[2] = (byte)appid; +// bytes[3] = 0; +// return bytes; +// } +// } +//} diff --git a/NSmartProxy/NSmartProxy.Data/Model.cs b/NSmartProxy/NSmartProxy.Data/Model.cs index bea6ff0..2ba5518 100644 --- a/NSmartProxy/NSmartProxy.Data/Model.cs +++ b/NSmartProxy/NSmartProxy.Data/Model.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using System.Linq; namespace NSmartProxy.Data { - public class Client + public class ClientModel { public int ClientId; //2 public List AppList; //3 * N @@ -22,22 +23,26 @@ public byte[] ToBytes() return listBytes.ToArray(); } - public static Client GetFromBytes(byte[] bytes) + public static ClientModel GetFromBytes(byte[] bytes, int totalLength = 0) { - Client client = new Client(); - client.ClientId = bytes[0] << 8 + bytes[1]; + if (totalLength == 0) + { + totalLength = bytes.Length; + } + ClientModel client = new ClientModel(); + client.ClientId = (bytes[0] << 8) + bytes[1]; client.AppList = new List(); - int appCount = (bytes.Length - 2) / 3; - if (((bytes.Length - 2) % 3) > 0) + int appCount = (totalLength - 2) / 3; + if (((totalLength - 2) % 3) > 0) { throw new Exception("error format"); } - for (int i = 2; i < appCount; i++) + for (int i = 0; i < appCount; i++) { App app = new App() { AppId = bytes[2 + 3 * i], - Port = bytes[3 + 3 * i] << 8 + bytes[4 + 3 * i] + Port = (bytes[3 + 3 * i] << 8) + bytes[4 + 3 * i] }; client.AppList.Add(app); } @@ -56,6 +61,52 @@ public class ClientIdAppId { public int ClientId; //2 public int AppId; //1 + public byte[] ToBytes() + { + byte[] bytes = new byte[3]; + byte[] clientIdBytres = StringUtil.IntTo2Bytes(ClientId); + bytes[0] = clientIdBytres[0]; + bytes[1] = clientIdBytres[1]; + bytes[2] = (byte)AppId; + return bytes; + } + + public static ClientIdAppId GetFromBytes(byte[] bytes) + { + return new ClientIdAppId + { + ClientId = StringUtil.DoubleBytesToInt(bytes[0], bytes[1]), + AppId = bytes[2] + }; + } + } + public class ClientApp + { + public int ClientId; + public int AppId; + public int TargetServicePort; + } + + public class ClientNewAppRequest + { + public int ClientId; //2 + public int ClientCount; //1 + public byte[] ToBytes() + { + byte[] bytes = new byte[3]; + byte[] clientIdBytres = StringUtil.IntTo2Bytes(ClientId); + bytes[0] = clientIdBytres[0]; + bytes[2] = (byte)ClientCount; + return bytes; + } + public static ClientNewAppRequest GetFromBytes(byte[] bytes) + { + return new ClientNewAppRequest + { + ClientId = StringUtil.DoubleBytesToInt(bytes[0], bytes[1]), + ClientCount = bytes[2] + }; + } } } diff --git a/NSmartProxy/NSmartProxy.Data/StringUtil.cs b/NSmartProxy/NSmartProxy.Data/StringUtil.cs index 57da1ea..6e405fb 100644 --- a/NSmartProxy/NSmartProxy.Data/StringUtil.cs +++ b/NSmartProxy/NSmartProxy.Data/StringUtil.cs @@ -9,7 +9,10 @@ public class StringUtil { public static byte[] IntTo2Bytes(int number) { - return System.BitConverter.GetBytes(number).Take(2).ToArray(); + byte[] bytes = new byte[2]; + bytes[0] = (byte)(number / 256); + bytes[1] = (byte)(number % 256); + return bytes; } /// @@ -18,12 +21,23 @@ public static byte[] IntTo2Bytes(int number) /// /// /// - public static byte[] Generate1stRequestBytes(int clientID, int appid) + public static byte[] ClientIDAppIdToBytes(int clientID, int appid) { byte[] bytes = IntTo2Bytes(clientID); bytes[2] = (byte)appid; return bytes.Take(3).ToArray(); } + + /// + /// 双字节转整型 + /// + /// + /// + /// + public static int DoubleBytesToInt(byte hByte, byte lByte) + { + return (hByte << 8) + lByte; + } } } diff --git a/NSmartProxy/NSmartProxy.Test/NSmartProxy.Test.csproj b/NSmartProxy/NSmartProxy.Test/NSmartProxy.Test.csproj index 423036a..eb8dda3 100644 --- a/NSmartProxy/NSmartProxy.Test/NSmartProxy.Test.csproj +++ b/NSmartProxy/NSmartProxy.Test/NSmartProxy.Test.csproj @@ -6,8 +6,7 @@ - - + diff --git a/NSmartProxy/NSmartProxy.Test/Program.cs b/NSmartProxy/NSmartProxy.Test/Program.cs index 8fc92e1..3672246 100644 --- a/NSmartProxy/NSmartProxy.Test/Program.cs +++ b/NSmartProxy/NSmartProxy.Test/Program.cs @@ -1,168 +1,27 @@ -//using System; -//using System.Net; -//using System.Net.Sockets; -//using System.Text; -//using System.Threading; - -//namespace NSmartProxy.Test -//{ -// // State object for reading client data asynchronously -// 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(); -// } - -// class Program -// { -// // Thread signal. -// public static ManualResetEvent allDone = new ManualResetEvent(false); - -// public static void StartListening() -// { -// // Establish the local endpoint for the socket. -// // The DNS name of the computer -// // running the listener is "host.contoso.com". -// IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName()); -// IPAddress ipAddress = ipHostInfo.AddressList[0]; -// IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8077); - -// // Create a TCP/IP socket. -// //Socket listener = new Socket(ipAddress.AddressFamily, -// // SocketType.Stream, ProtocolType.Tcp); - -// Socket listener = new Socket(AddressFamily.InterNetwork, -// SocketType.Stream, ProtocolType.Tcp); - -// // Bind the socket to the local endpoint and listen for incoming connections. -// try -// { -// listener.Bind(localEndPoint); -// 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... Thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString()); - -// listener.BeginAccept( -// new AsyncCallback(AcceptCallback), -// listener); - -// // Wait until a connection is made before continuing. -// allDone.WaitOne(); -// } - -// } -// catch (Exception e) -// { -// Console.WriteLine(e.ToString()); -// } - -// Console.WriteLine("\nPress ENTER to continue..."); -// Console.Read(); - -// } - -// public static void AcceptCallback(IAsyncResult ar) -// { -// // Signal the main thread to continue. -// allDone.Set(); -// Console.WriteLine("Connected!! Thread ID is:" + Thread.CurrentThread.ManagedThreadId.ToString()); -// // 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); -// } - -// public static 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("", StringComparison.Ordinal) > -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); -// } -// } -// } - -// private static 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); -// } - -// private static 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 static int Main(String[] args) -// { -// StartListening(); -// return 0; -// } -// } -//} +using System; +using System.Collections.Generic; +using System.Text; +using NSmartProxy.Data; + +namespace NSmartProxy +{ + class Program + { + static void Main(string[] args) + { + //ClientModel cm = new ClientModel(); + //cm.AppList = new List { new App { AppId = 1, Port = 8091 }, new App { AppId = 2, Port = 8092 }, new App { AppId = 3, Port = 8093 } }; + //cm.ClientId = 1000; + //byte[] d = cm.ToBytes(); + //ClientModel cm2 = ClientModel.GetFromBytes(d); + + + ClientIdAppId cia = new ClientIdAppId(); + cia.AppId = 123; + cia.ClientId = 2323; + var bt = cia.ToBytes(); + var cia2 = ClientIdAppId.GetFromBytes(bt); + Console.Read(); + } + } +} diff --git a/NSmartProxy/NSmartProxy.Test/Program_client.cs b/NSmartProxy/NSmartProxy.Test/Program_client.cs index 2d58bb6..7ebfa0e 100644 --- a/NSmartProxy/NSmartProxy.Test/Program_client.cs +++ b/NSmartProxy/NSmartProxy.Test/Program_client.cs @@ -8,23 +8,23 @@ namespace NSmartProxy.Test { - class Program - { - public static void Main(String[] args) - { - ////TcpListener listener = new TcpListener(IPAddress.Any, 6666); - //TcpClient tcpClient = new TcpClient(); - //tcpClient.Connect(IPAddress.Parse("172.20.66.84"),80); - //TcpListener listener = new TcpListener(IPAddress.Any, 89); - //var client = listener.AcceptTcpClient(); - //byte[] buf = new byte[1024]; + //class Program + //{ + // public static void Main(String[] args) + // { + // ////TcpListener listener = new TcpListener(IPAddress.Any, 6666); + // //TcpClient tcpClient = new TcpClient(); + // //tcpClient.Connect(IPAddress.Parse("172.20.66.84"),80); + // //TcpListener listener = new TcpListener(IPAddress.Any, 89); + // //var client = listener.AcceptTcpClient(); + // //byte[] buf = new byte[1024]; - //client.GetStream().Read(buf, 0, buf.Length); - ClientConnectionManager ccm = ClientConnectionManager.GetInstance(); - ClientConnectionManager ccm1 = ClientConnectionManager.GetInstance(); - ClientConnectionManager ccm2 = ClientConnectionManager.GetInstance(); + // //client.GetStream().Read(buf, 0, buf.Length); + // ClientConnectionManager ccm = ClientConnectionManager.GetInstance(); + // ClientConnectionManager ccm1 = ClientConnectionManager.GetInstance(); + // ClientConnectionManager ccm2 = ClientConnectionManager.GetInstance(); - Console.Read(); - } - } + // Console.Read(); + // } + //} } diff --git a/NSmartProxy/NSmartProxy/ClientConnectionManager.cs b/NSmartProxy/NSmartProxy/ClientConnectionManager.cs index 65a46af..ba3170b 100644 --- a/NSmartProxy/NSmartProxy/ClientConnectionManager.cs +++ b/NSmartProxy/NSmartProxy/ClientConnectionManager.cs @@ -1,4 +1,5 @@ -using System; +using NSmartProxy.Data; +using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; @@ -7,14 +8,21 @@ namespace NSmartProxy { - public struct TcpTunnel + public struct ClientIDAppID { public int ClientID; public int AppID; - public int Port; } public class ClientConnectionManager { + //端口和ClientIDAppID的映射关系 + public Dictionary PortAppMap; + //app和代理客户端socket之间的映射关系 + public Dictionary> AppTcpClientMap = new Dictionary>(); + + //已注册的clientID,和appid之间的关系,appid序号=元素下标序号+1 + public Dictionary> RegisteredClient = new Dictionary>(); + private ClientConnectionManager() { Console.WriteLine("ClientManager initialized"); @@ -24,9 +32,9 @@ private ClientConnectionManager() /// /// 客户端,appid,端口映射 /// - public Dictionary> ServiceClientsDict = new Dictionary>(); + // public Dictionary> ServiceClientsDict = new Dictionary>(); //port->tcptunnels->tcpclients - private Dictionary> ServiceClientQueueCollection = new Dictionary>(); + // private Dictionary> ServiceClientQueueCollection = new Dictionary>(); private object _lockObject = new Object(); private object _lockObject2 = new Object(); @@ -43,56 +51,67 @@ private async Task ListenServiceClient() //立即侦听一次并且分配连接 byte[] bytes = new byte[4]; await incomeClient.GetStream().ReadAsync(bytes); + var clientIdAppId = GetAppFromBytes(bytes); //根据不同的服务端appid安排不同的连接池 - AddClient(GetTcpTunnelFromBytes(bytes), incomeClient); + AppTcpClientMap[clientIdAppId].Add(incomeClient); + //AddClient(GetTcpTunnelFromBytes(bytes), incomeClient); } } //可能要改成字典 //private Queue ServiceClientQueue = new Queue(); - + private static ClientConnectionManager Instance = new Lazy(() => new ClientConnectionManager()).Value; - public void AddClient(TcpTunnel tcpTunnel, TcpClient client) - { - ServiceClientQueueCollection[tcpTunnel].Enqueue(client); - } + //public void AddClient(TcpTunnel tcpTunnel, TcpClient client) + //{ + // ServiceClientQueueCollection[tcpTunnel].Enqueue(client); + //} public static ClientConnectionManager GetInstance() { return Instance; } - public TcpClient GetClient(int port) + public TcpClient GetClient(int consumerPort) { - ServiceClientsDict[port][0] - return ServiceClientQueueCollection[tcpTunnel].Dequeue(); + //从字典的list中取出tcpclient,并将其移除 + ClientIDAppID clientappid = PortAppMap[consumerPort]; + TcpClient client = AppTcpClientMap[clientappid][0]; + AppTcpClientMap[clientappid].Remove(client); + return client; + //ServiceClientsDict[port][0] + //return ServiceClientQueueCollection[tcpTunnel].Dequeue(); } + //通过客户端的id请求,分配好服务端端口和appid交给客户端 //arrange ConfigId from top 4 bytes which received from client. //response: // 2 1 1 1 1 ...N // clientid appid port appid2 port2 - public byte[] ArrageConfigIds(byte[] fourBytes) + public byte[] ArrageConfigIds(byte[] appRequestBytes) { - byte[] arrangedBytes = new byte[256]; - int clientId = fourBytes[0] << 8 + fourBytes[1]; - int appCount = (int)fourBytes[2]; + // byte[] arrangedBytes = new byte[256]; + ClientModel clientModel = new ClientModel(); + int clientId = (appRequestBytes[0] << 8) + appRequestBytes[1]; + int appCount = (int)appRequestBytes[2]; if (clientId == 0) { lock (_lockObject) { byte[] tempClientIdBytes = new byte[2]; + //分配clientid for (int i = 0; i < 10000; i++) { _rand.NextBytes(tempClientIdBytes); - int tempClientId = tempClientIdBytes[0] << 8 + tempClientIdBytes[1]; - if (!ServiceClientsDict.ContainsKey(tempClientId)) + int tempClientId = (tempClientIdBytes[0] << 8) + tempClientIdBytes[1]; + if (!RegisteredClient.ContainsKey(tempClientId)) { - arrangedBytes[0] = tempClientIdBytes[0]; - arrangedBytes[1] = tempClientIdBytes[1]; + + clientModel.ClientId = tempClientId; clientId = tempClientId; - ServiceClientsDict.Add(clientId, new List()); + //注册客户端 + RegisteredClient.Add(tempClientId, new List()); break; } } @@ -100,44 +119,63 @@ public byte[] ArrageConfigIds(byte[] fourBytes) } else { - arrangedBytes[0] = fourBytes[0]; - arrangedBytes[1] = fourBytes[1]; + clientModel.ClientId = clientId; } lock (_lockObject2) { - int maxAppCount = ServiceClientsDict[clientId].Count; + //循环获取appid,appid是元素下标+1 + int maxAppCount = RegisteredClient[clientId].Count; //增加请求的客户端 int[] ports = NetworkUtil.FindAvailableTCPPorts(20000, appCount); + clientModel.AppList = new List(appCount); for (int i = 0; i < appCount; i++) { - int arrangedAppid = maxAppCount + i; + int arrangedAppid = maxAppCount + i + 1; if (arrangedAppid > 255) throw new Exception("Stack overflow."); //获取可用端口,增加到tcpclient - ServiceClientsDict[clientId].Add(new TcpTunnel() + RegisteredClient[clientId].Add(new ClientIDAppID { ClientID = clientId, - AppID = arrangedAppid, + AppID = arrangedAppid + }); + clientModel.AppList.Add(new App + { + AppId = arrangedAppid, Port = ports[i] }); - arrangedBytes[i + 2] = (byte)arrangedAppid; - } - } + PortAppMap[ports[i]] = new ClientIDAppID + { + ClientID = clientId, + AppID = arrangedAppid + }; - return arrangedBytes; + + } + } + return clientModel.ToBytes(); } - /// - /// 解析客户端请求的tcp连接分类 - /// - /// - /// - private TcpTunnel GetTcpTunnelFromBytes(byte[] bytes) + ///// + ///// 解析客户端请求的tcp连接分类 + ///// + ///// + ///// + //private TcpTunnel GetTcpTunnelFromBytes(byte[] bytes) + //{ + // return new TcpTunnel() + // { + // ClientID = (bytes[0] << 8) + bytes[1], + // AppID = bytes[2], + // Port = 0 + // }; + //} + + private ClientIDAppID GetAppFromBytes(byte[] bytes) { - return new TcpTunnel() + return new ClientIDAppID() { - ClientID = bytes[0] << 8 + bytes[1], - AppID = bytes[2], - Port = 0 + ClientID = (bytes[0] << 8) + bytes[1], + AppID = bytes[2] }; } } diff --git a/NSmartProxy/NSmartProxy/NSmartProxy.csproj b/NSmartProxy/NSmartProxy/NSmartProxy.csproj index 23df604..eb8dda3 100644 --- a/NSmartProxy/NSmartProxy/NSmartProxy.csproj +++ b/NSmartProxy/NSmartProxy/NSmartProxy.csproj @@ -5,4 +5,8 @@ netcoreapp2.1 + + + + diff --git a/NSmartProxy/NSmartProxy/Server.cs b/NSmartProxy/NSmartProxy/Server.cs index 3f92c12..42735d4 100644 --- a/NSmartProxy/NSmartProxy/Server.cs +++ b/NSmartProxy/NSmartProxy/Server.cs @@ -60,10 +60,10 @@ public async Task Start() // //get consumer client first. - foreach (var kv in ConnectionManager.ServiceClientsDict) + foreach (var kv in ConnectionManager.PortAppMap) { //TcpTunnel tunnel = kv.Value; - var taskResultConsumer = AcceptConsumeAsync(tunnel, accepting.Token); + var taskResultConsumer = AcceptConsumeAsync(kv.Key, accepting.Token); } @@ -96,18 +96,18 @@ private async Task AcceptConfigRequest(TcpListener listenerConfigService) { while (1 == 1) { - byte[] fourBytes = new byte[4]; + byte[] appRequestBytes = new byte[4]; listenerConfigService.Start(100); var listener = await listenerConfigService.AcceptTcpClientAsync(); var nstream = listener.GetStream(); - int resultByte = await nstream.ReadAsync(fourBytes); + int resultByte = await nstream.ReadAsync(appRequestBytes); if (resultByte == 0) { Console.WriteLine("invalid request"); } - byte[] arrangedIds = ConnectionManager.ArrageConfigIds(fourBytes); + byte[] arrangedIds = ConnectionManager.ArrageConfigIds(appRequestBytes); await nstream.WriteAsync(arrangedIds); } } @@ -120,8 +120,9 @@ private async Task AcceptConfigRequest(TcpListener listenerConfigService) /// /// /// - async Task AcceptConsumeAsync(TcpTunnel tcpTunnel ,TcpListener consumerlistener, CancellationToken ct) + async Task AcceptConsumeAsync(int consumerPort, CancellationToken ct) { + var consumerlistener = new TcpListener(IPAddress.Any,consumerPort); consumerlistener.Start(1000); //给两个listen,同时监听3端 var clientCounter = 0; @@ -134,7 +135,7 @@ async Task AcceptConsumeAsync(TcpTunnel tcpTunnel ,TcpListener consumerlistener, //连接成功 连接provider端 clientCounter++; //需要端口 - TcpClient s2pClient = ConnectionManager.GetClient(tcpTunnel); + TcpClient s2pClient = ConnectionManager.GetClient(consumerPort); Task transferResult = TcpTransferAsync(consumerlistener, consumerClient, s2pClient, clientCounter, ct); }