diff --git a/FastTunnel.Client/appsettings.json b/FastTunnel.Client/appsettings.json index 5ef2270..c22829e 100644 --- a/FastTunnel.Client/appsettings.json +++ b/FastTunnel.Client/appsettings.json @@ -2,7 +2,7 @@ "Logging": { "LogLevel": { // Trace Debug Information Warning Error - "Default": "Information", + "Default": "Trace", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } @@ -10,8 +10,8 @@ "ClientSettings": { "Server": { // 服务端ip/域名 - "ServerAddr": "test.cc", - //"ServerAddr": "127.0.0.1", + //"ServerAddr": "my.com", + "ServerAddr": "127.0.0.1", // 服务端监听的通信端口 "ServerPort": 1271 }, @@ -21,13 +21,18 @@ "LocalIp": "127.0.0.1", // 站点监听的端口号 - "LocalPort": 9529, + "LocalPort": 8090, // 子域名, 访问本站点时的url为 http://{SubDomain}.{WebDomain}:{WebProxyPort}/ "SubDomain": "test" // test.test.cc // 附加域名,需要解析域名A记录至服务的ip地址) // "WWW": [ "www.abc.com", "test111.test.cc" ] + }, + { + "LocalIp": "127.0.0.1", + "LocalPort": 8091, + "SubDomain": "test1" } ], @@ -38,9 +43,14 @@ */ "SSH": [ { - "LocalIp": "test.cc", + "LocalIp": "127.0.0.1", "LocalPort": 8090, - "RemotePort": 9999 + "RemotePort": 7090 + }, + { + "LocalIp": "127.0.0.1", + "LocalPort": 8091, + "RemotePort": 7091 }, { "LocalIp": "192.168.0.91", diff --git a/FastTunnel.Core/Client/FastTunnelClient.cs b/FastTunnel.Core/Client/FastTunnelClient.cs index f2056b4..ab42ea4 100644 --- a/FastTunnel.Core/Client/FastTunnelClient.cs +++ b/FastTunnel.Core/Client/FastTunnelClient.cs @@ -191,20 +191,103 @@ namespace FastTunnel.Core.Client // 心跳开始 timer_heart.Start(); - await new PipeHepler(_client, ProceccLine).ProcessLinesAsync(); + var th = new Thread(ReceiveServer); + th.Start(_client); + //await new PipeHepler(_client, ProceccLine).ProcessLinesAsync(); + } + + private void ReceiveServer(object obj) + { + var client = obj as Socket; + byte[] buffer = new byte[1024]; + + string lastBuffer = string.Empty; + int n = 0; + + while (true) + { + try + { + n = client.Receive(buffer); + if (n == 0) + { + client.Shutdown(SocketShutdown.Both); + break; + } + } + /// + catch (SocketException socketEx) + { + // Connection timed out. + if (socketEx.ErrorCode == 10060) + { + _logger.LogInformation("Connection timed out"); + } + else + { + _logger.LogError(socketEx); + } + + break; + } + catch (Exception ex) + { + _logger.LogError(ex); + break; + } + + string words = Encoding.UTF8.GetString(buffer, 0, n); + if (!string.IsNullOrEmpty(lastBuffer)) + { + words = lastBuffer + words; + lastBuffer = null; + } + + var msgs = words.Split("\n"); + + _logger.LogDebug("recive from server:" + words); + + try + { + foreach (var item in msgs) + { + if (string.IsNullOrEmpty(item)) + continue; + + if (item.EndsWith("}")) + { + HandleServerRequest(item); + } + else + { + lastBuffer = item; + } + } + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + continue; + } + } + + _logger.LogInformation("stop receive from server"); } private bool ProceccLine(Socket socket, byte[] line) { - try + Task.Run(() => { - var cmd = Encoding.UTF8.GetString(line); - HandleServerRequest(cmd); - } - catch (Exception ex) - { - _logger.LogError(ex); - } + try + { + var cmd = Encoding.UTF8.GetString(line); + HandleServerRequest(cmd); + } + catch (Exception ex) + { + _logger.LogError(ex); + } + }); return true; } @@ -212,6 +295,11 @@ namespace FastTunnel.Core.Client private void HandleServerRequest(string words) { var Msg = JsonConvert.DeserializeObject>(words); + if (Msg.MessageType!= MessageType.Heart) + { + _logger.LogDebug($"HandleServerRequest {words}"); + } + IClientHandler handler; switch (Msg.MessageType) { diff --git a/FastTunnel.Core/Dispatchers/HttpDispatcherV2.cs b/FastTunnel.Core/Dispatchers/HttpDispatcherV2.cs index 2b2fb9f..5fc22ec 100644 --- a/FastTunnel.Core/Dispatchers/HttpDispatcherV2.cs +++ b/FastTunnel.Core/Dispatchers/HttpDispatcherV2.cs @@ -12,6 +12,7 @@ using System.Text.RegularExpressions; using System.Net.Http; using System.IO; using FastTunnel.Core.Server; +using System.Diagnostics; namespace FastTunnel.Core.Dispatchers { @@ -32,7 +33,10 @@ namespace FastTunnel.Core.Dispatchers public void Dispatch(AsyncUserToken token, string words) { - _logger.LogDebug("=======Dispatch HTTP========"); + _logger.LogDebug($"=======Dispatch HTTP {token.RequestId}========"); + + Stopwatch sw = new Stopwatch(); + sw.Start(); // 1.检查白名单 try @@ -54,8 +58,6 @@ namespace FastTunnel.Core.Dispatchers _logger.LogError(ex); } - _logger.LogDebug("=======Dispatch Matches========"); - string Host; MatchCollection collection = Regex.Matches(words, pattern); if (collection.Count == 0) @@ -74,7 +76,7 @@ namespace FastTunnel.Core.Dispatchers _logger.LogDebug(Host.Replace("\r", "")); var domain = Host.Split(":")[1].Trim(); - _logger.LogDebug($"=======Dispatch domain:{domain}========"); + _logger.LogDebug($"=======Dispatch domain:{domain} {token.RequestId} ========"); // 判断是否为ip if (IsIpDomian(domain)) @@ -87,34 +89,36 @@ namespace FastTunnel.Core.Dispatchers WebInfo web; if (!_fastTunnelServer.WebList.TryGetValue(domain, out web)) { - _logger.LogDebug($"=======Dispatch 未登录========"); + _logger.LogDebug($"=======站点未登录 {token.RequestId}========"); HandlerClientNotOnLine(token.Socket, domain); return; } - _logger.LogDebug($"=======Dispatch 已找到========"); - var msgid = Guid.NewGuid().ToString(); - _fastTunnelServer.RequestTemp.TryAdd(msgid, new NewRequest + _logger.LogDebug($"=======找到映射的站点 {token.RequestId}========"); + _fastTunnelServer.RequestTemp.TryAdd(token.RequestId, new NewRequest { CustomerClient = token.Socket, Buffer = token.Recived }); - _logger.LogDebug($"=======Dispatch 发送msg========"); - try { - _logger.LogDebug($"=======OK========"); - web.Socket.SendCmd(new Message { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = msgid, WebConfig = web.WebConfig } }); + sw.Stop(); + _logger.LogDebug($"[寻找路由耗时]:{sw.ElapsedMilliseconds}ms"); - _logger.LogDebug($"=======Dispatch OK========"); + sw.Restart(); + web.Socket.SendCmd(new Message { MessageType = MessageType.S_NewCustomer, Content = new NewCustomerMassage { MsgId = token.RequestId, WebConfig = web.WebConfig } }); + + sw.Stop(); + _logger.LogDebug($"[发送NewCustomer指令耗时]:{sw.ElapsedMilliseconds}"); + + _logger.LogDebug($"=======发送请求成功 {token.RequestId}========"); } catch (Exception) { + _logger.LogDebug($"=======客户端不在线 {token.RequestId}========"); HandlerClientNotOnLine(token.Socket, domain); - _logger.LogDebug($"=======Dispatch 移除========"); - // 移除 _fastTunnelServer.WebList.TryRemove(domain, out _); } diff --git a/FastTunnel.Core/FastTunnel.Core.csproj b/FastTunnel.Core/FastTunnel.Core.csproj index 5ffec5a..e5e742f 100644 --- a/FastTunnel.Core/FastTunnel.Core.csproj +++ b/FastTunnel.Core/FastTunnel.Core.csproj @@ -18,7 +18,7 @@ git FastTunnel.Core FastTunnel.Core - 1.1.2 + 1.1.3 diff --git a/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs b/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs index 9350ba2..56b99c3 100644 --- a/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs +++ b/FastTunnel.Core/Handlers/Client/HttpRequestHandler.cs @@ -10,24 +10,41 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using FastTunnel.Core.Sockets; +using Microsoft.Extensions.Logging; +using FastTunnel.Core.Utility.Extensions; namespace FastTunnel.Core.Handlers.Client { public class HttpRequestHandler : IClientHandler { + ILogger _logger; + + public HttpRequestHandler(ILogger logger) + { + _logger = logger; + } + public void HandlerMsg(FastTunnelClient cleint, Message Msg) { var request = Msg.Content.ToObject(); + var interval = long.Parse(DateTime.Now.GetChinaTicks()) - long.Parse(request.MsgId.Split('_')[0]); + + _logger.LogDebug($"Start SwapMassage {request.MsgId} 延迟时间:{interval}ms"); + var connecter = new DnsSocket(cleint.Server.ServerAddr, cleint.Server.ServerPort); connecter.Connect(); connecter.Send(new Message { MessageType = MessageType.C_SwapMsg, Content = new SwapMassage(request.MsgId) }); + _logger.LogDebug($"连接server成功 {request.MsgId}"); var localConnecter = new DnsSocket(request.WebConfig.LocalIp, request.WebConfig.LocalPort); try { localConnecter.Connect(); + _logger.LogDebug($"连接本地成功 {request.MsgId}"); + + new SocketSwap(connecter.Socket, localConnecter.Socket, _logger, request.MsgId).StartSwap(); } catch (SocketException sex) { @@ -59,8 +76,6 @@ namespace FastTunnel.Core.Handlers.Client localConnecter.Close(); throw; } - - new SocketSwap(connecter.Socket, localConnecter.Socket).StartSwap(); } } } diff --git a/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs b/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs index b2dbd17..bf0b62a 100644 --- a/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs +++ b/FastTunnel.Core/Handlers/Client/NewSSHHandler.cs @@ -6,11 +6,18 @@ using System; using System.Collections.Generic; using System.Text; using FastTunnel.Core.Sockets; +using Microsoft.Extensions.Logging; namespace FastTunnel.Core.Handlers.Client { public class NewSSHHandler : IClientHandler { + ILogger _logger; + public NewSSHHandler(ILogger logger) + { + _logger = logger; + } + public void HandlerMsg(FastTunnelClient cleint, Message Msg) { var request_ssh = Msg.Content.ToObject(); @@ -21,7 +28,7 @@ namespace FastTunnel.Core.Handlers.Client var localConnecter_ssh = new DnsSocket(request_ssh.SSHConfig.LocalIp, request_ssh.SSHConfig.LocalPort); localConnecter_ssh.Connect(); - new SocketSwap(connecter_ssh.Socket, localConnecter_ssh.Socket).StartSwap(); + new SocketSwap(connecter_ssh.Socket, localConnecter_ssh.Socket, _logger, request_ssh.MsgId).StartSwap(); } } } diff --git a/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs b/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs index 61790b3..5c14958 100644 --- a/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs +++ b/FastTunnel.Core/Handlers/Server/SwapMessageHandler.cs @@ -28,10 +28,14 @@ namespace FastTunnel.Core.Handlers.Server var SwapMsg = msg.Content.ToObject(); NewRequest request; + _logger.LogDebug($"响应NewCustomer:{SwapMsg.msgId}"); if (!string.IsNullOrEmpty(SwapMsg.msgId) && server.RequestTemp.TryGetValue(SwapMsg.msgId, out request)) { server.RequestTemp.TryRemove(SwapMsg.msgId, out _); - new SocketSwap(request.CustomerClient, client) + + _logger.LogDebug($"SwapMassage:{SwapMsg.msgId}"); + + new SocketSwap(request.CustomerClient, client, _logger, SwapMsg.msgId) .BeforeSwap(() => { if (request.Buffer != null) client.Send(request.Buffer); diff --git a/FastTunnel.Core/Listener/ClientListenerV2.cs b/FastTunnel.Core/Listener/ClientListenerV2.cs index 54b3b77..7914f98 100644 --- a/FastTunnel.Core/Listener/ClientListenerV2.cs +++ b/FastTunnel.Core/Listener/ClientListenerV2.cs @@ -42,10 +42,10 @@ namespace FastTunnel.Core.Listener _heartHandler = new HeartMessageHandler(); _swapMsgHandler = new SwapMessageHandler(_logger); - server = new Server.Server(1000, 100); + server = new Server.Server(2000, 100, _logger); } - public void Start(int backlog = 100) + public void Start() { IPAddress ipa = IPAddress.Parse(ListenIp); IPEndPoint localEndPoint = new IPEndPoint(ipa, ListenPort); diff --git a/FastTunnel.Core/Listener/HttpListenerV2.cs b/FastTunnel.Core/Listener/HttpListenerV2.cs index 29720df..1f72e40 100644 --- a/FastTunnel.Core/Listener/HttpListenerV2.cs +++ b/FastTunnel.Core/Listener/HttpListenerV2.cs @@ -30,7 +30,7 @@ namespace FastTunnel.Core.Listener this.ListenIp = ip; this.ListenPort = port; - server = new Server.Server(1000, 512); + server = new Server.Server(500, 512, _logger); } public void Start(IListenerDispatcher requestDispatcher, int backlog = 100) @@ -49,7 +49,6 @@ namespace FastTunnel.Core.Listener { try { - Console.WriteLine(words); _requestDispatcher.Dispatch(token, words); return false; } diff --git a/FastTunnel.Core/Server/AsyncUserToken.cs b/FastTunnel.Core/Server/AsyncUserToken.cs index fbf0011..9a66c0c 100644 --- a/FastTunnel.Core/Server/AsyncUserToken.cs +++ b/FastTunnel.Core/Server/AsyncUserToken.cs @@ -14,5 +14,7 @@ namespace FastTunnel.Core.Server public string MassgeTemp { get; set; } public byte[] Recived { get; set; } + + public string RequestId { get; set; } } } diff --git a/FastTunnel.Core/Server/BufferManeger.cs b/FastTunnel.Core/Server/BufferManeger.cs index cc20bf5..e95bc8c 100644 --- a/FastTunnel.Core/Server/BufferManeger.cs +++ b/FastTunnel.Core/Server/BufferManeger.cs @@ -40,7 +40,6 @@ namespace FastTunnel.Core.Server // true if the buffer was successfully set, else false public bool SetBuffer(SocketAsyncEventArgs args) { - if (m_freeIndexPool.Count > 0) { args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize); @@ -51,6 +50,7 @@ namespace FastTunnel.Core.Server { return false; } + args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize); m_currentIndex += m_bufferSize; } diff --git a/FastTunnel.Core/Server/PipeHepler.cs b/FastTunnel.Core/Server/PipeHepler.cs index c4e2bc8..7114bcd 100644 --- a/FastTunnel.Core/Server/PipeHepler.cs +++ b/FastTunnel.Core/Server/PipeHepler.cs @@ -13,6 +13,7 @@ namespace FastTunnel.Core.Server { Socket m_socket; Func processLine; + const int minimumBufferSize = 512; public PipeHepler(Socket socket, Func processLine) { @@ -30,8 +31,6 @@ namespace FastTunnel.Core.Server private async Task FillPipeAsync(PipeWriter writer) { - const int minimumBufferSize = 512; - while (true) { // Allocate at least 512 bytes from the PipeWriter. @@ -77,7 +76,7 @@ namespace FastTunnel.Core.Server if (!processLine(m_socket, line.ToArray())) { // 停止继续监听 - + break; } } diff --git a/FastTunnel.Core/Server/Server.cs b/FastTunnel.Core/Server/Server.cs index 68d3188..bb6add7 100644 --- a/FastTunnel.Core/Server/Server.cs +++ b/FastTunnel.Core/Server/Server.cs @@ -3,6 +3,8 @@ // is sent back to the client. The read and echo back to the client pattern // is continued until the client disconnects. using FastTunnel.Core.Extensions; +using FastTunnel.Core.Utility.Extensions; +using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Net; @@ -28,6 +30,9 @@ namespace FastTunnel.Core.Server Func m_handller; string m_sectionFlag; + IPEndPoint _localEndPoint; + + ILogger _logger; // Create an uninitialized server instance. // To start the server listening for connection requests @@ -35,8 +40,9 @@ namespace FastTunnel.Core.Server // // the maximum number of connections the sample is designed to handle simultaneously // buffer size to use for each socket I/O operation - public Server(int numConnections, int receiveBufferSize) + public Server(int numConnections, int receiveBufferSize, ILogger logger) { + _logger = logger; //m_totalBytesRead = 0; m_numConnectedSockets = 0; m_numConnections = numConnections; @@ -47,6 +53,7 @@ namespace FastTunnel.Core.Server receiveBufferSize); m_readWritePool = new SocketAsyncEventArgsPool(numConnections); + m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); } @@ -88,12 +95,13 @@ namespace FastTunnel.Core.Server { m_handller = handller; m_sectionFlag = sectionFlag; + _localEndPoint = localEndPoint; // create the socket which listens for incoming connections listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(localEndPoint); // start the server with a listen backlog of 100 connections - listenSocket.Listen(100); + listenSocket.Listen(); // post accepts on the listening socket StartAccept(null); @@ -117,6 +125,7 @@ namespace FastTunnel.Core.Server } m_maxNumberAcceptedClients.WaitOne(); + bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg); if (!willRaiseEvent) { @@ -126,7 +135,6 @@ namespace FastTunnel.Core.Server // This method is the callback method associated with Socket.AcceptAsync // operations and is invoked when an accept operation is complete - // void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) { ProcessAccept(e); @@ -135,15 +143,19 @@ namespace FastTunnel.Core.Server private void ProcessAccept(SocketAsyncEventArgs e) { Interlocked.Increment(ref m_numConnectedSockets); + _logger.LogInformation($"[当前连接数]:{_localEndPoint.Port} | {m_numConnectedSockets}"); // Get the socket for the accepted client connection and put it into the //ReadEventArg object user token SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop(); - ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket; - ((AsyncUserToken)readEventArgs.UserToken).MassgeTemp = null; - ((AsyncUserToken)readEventArgs.UserToken).Recived = null; + var token = readEventArgs.UserToken as AsyncUserToken; + token.Socket = e.AcceptSocket; + token.MassgeTemp = null; + token.Recived = null; + token.RequestId = $"{DateTime.Now.GetChinaTicks()}_{Guid.NewGuid().ToString().Replace("-", string.Empty)}"; + + _logger.LogDebug($"Accept {token.RequestId}"); - Console.WriteLine("ReceiveAsync"); // As soon as the client is connected, post a receive to the connection bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs); if (!willRaiseEvent) @@ -181,10 +193,11 @@ namespace FastTunnel.Core.Server private void ProcessReceive(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; + _logger.LogDebug($"[ProcessReceive]: {_localEndPoint.Port} | {token.RequestId}"); if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { - //increment the count of the total bytes receive by the server - //Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); + // increment the count of the total bytes receive by the server + // Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); if (token.Recived != null) { byte[] resArr = new byte[token.Recived.Length + e.BytesTransferred]; @@ -292,6 +305,7 @@ namespace FastTunnel.Core.Server // decrement the counter keeping track of the total number of clients connected to the server Interlocked.Decrement(ref m_numConnectedSockets); + _logger.LogInformation($"[SocketCount]:{_localEndPoint.Port} | {m_numConnectedSockets}"); // Free the SocketAsyncEventArg so they can be reused by another client m_readWritePool.Push(e); diff --git a/FastTunnel.Core/Services/ServiceFastTunnelClient.cs b/FastTunnel.Core/Services/ServiceFastTunnelClient.cs index 36995e2..738f934 100644 --- a/FastTunnel.Core/Services/ServiceFastTunnelClient.cs +++ b/FastTunnel.Core/Services/ServiceFastTunnelClient.cs @@ -41,7 +41,6 @@ namespace FastTunnel.Core.Services return Task.CompletedTask; } - private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { try diff --git a/FastTunnel.Core/Sockets/AsyncSocketSwap.cs b/FastTunnel.Core/Sockets/AsyncSocketSwap.cs index 0d5d10b..7ee817f 100644 --- a/FastTunnel.Core/Sockets/AsyncSocketSwap.cs +++ b/FastTunnel.Core/Sockets/AsyncSocketSwap.cs @@ -93,7 +93,6 @@ namespace FastTunnel.Core.Sockets var token = e.UserToken as SwapUserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { - Console.WriteLine("ProcessReceive:" + e.BytesTransferred); e.SetBuffer(e.Offset, 512); if (!token.Sender.SendAsync(e)) { diff --git a/FastTunnel.Core/Sockets/ConnectSocket.cs b/FastTunnel.Core/Sockets/ConnectSocket.cs new file mode 100644 index 0000000..6d26258 --- /dev/null +++ b/FastTunnel.Core/Sockets/ConnectSocket.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Sockets +{ + public class ConnectSocket + { + string m_server; + int m_port; + + public ConnectSocket(string server, int port) + { + this.m_port = port; + this.m_server = server; + } + + public Socket Connect() + { + Socket s = null; + IPHostEntry hostEntry = null; + + // Get host related information. + hostEntry = Dns.GetHostEntry(m_server); + + // Loop through the AddressList to obtain the supported AddressFamily. This is to avoid + // an exception that occurs when the host IP Address is not compatible with the address family + // (typical in the IPv6 case). + foreach (IPAddress address in hostEntry.AddressList) + { + IPEndPoint ipe = new IPEndPoint(address, m_port); + Socket tempSocket = + new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + + tempSocket.Connect(ipe); + + if (tempSocket.Connected) + { + s = tempSocket; + break; + } + else + { + continue; + } + } + + return s; + } + } +} diff --git a/FastTunnel.Core/Sockets/SocketSwap.cs b/FastTunnel.Core/Sockets/SocketSwap.cs index ef22524..48ccf87 100644 --- a/FastTunnel.Core/Sockets/SocketSwap.cs +++ b/FastTunnel.Core/Sockets/SocketSwap.cs @@ -1,6 +1,9 @@ using FastTunnel.Core.Dispatchers; +using FastTunnel.Core.Utility.Extensions; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Net.Sockets; using System.Text; using System.Threading; @@ -9,9 +12,12 @@ namespace FastTunnel.Core.Sockets { public class SocketSwap : ISocketSwap { - private Socket _sockt1; - private Socket _sockt2; - bool Swaped = false; + private readonly Socket m_sockt1; + private readonly Socket m_sockt2; + private readonly string m_msgId = null; + private readonly ILogger m_logger; + + private bool Swaped = false; private class Channel { @@ -20,100 +26,116 @@ namespace FastTunnel.Core.Sockets public Socket Receive { get; set; } } - public SocketSwap(Socket sockt1, Socket sockt2) + public SocketSwap(Socket sockt1, Socket sockt2, ILogger logger, string msgId) { - _sockt1 = sockt1; - _sockt2 = sockt2; + m_sockt1 = sockt1; + m_sockt2 = sockt2; + m_msgId = msgId; + m_logger = logger; } public void StartSwap() { + m_logger?.LogDebug($"StartSwap {m_msgId}"); + Swaped = true; ThreadPool.QueueUserWorkItem(swapCallback, new Channel { - Send = _sockt1, - Receive = _sockt2 + Send = m_sockt1, + Receive = m_sockt2 }); ThreadPool.QueueUserWorkItem(swapCallback, new Channel { - Send = _sockt2, - Receive = _sockt1 + Send = m_sockt2, + Receive = m_sockt1 }); } private void swapCallback(object state) { + m_logger?.LogDebug($"swapCallback {m_msgId}"); var chanel = state as Channel; - byte[] result = new byte[1024]; + byte[] result = new byte[512]; while (true) { + int num; + try { - if (!chanel.Receive.Connected) + try + { + num = chanel.Receive.Receive(result, result.Length, SocketFlags.None); + } + catch (Exception) + { + closeSocket("Revice Fail"); break; - int num = chanel.Receive.Receive(result, result.Length, SocketFlags.None); + } if (num == 0) { - chanel.Receive.Close(); - - try - { - // Release the socket.// - chanel.Send.Shutdown(SocketShutdown.Both); - } - catch { } - finally - { - chanel.Send.Close(); - } + closeSocket("Normal Close"); break; } - if (!chanel.Send.Connected) - break; - - // var str = Encoding.UTF8.GetString(result, 0, num); - - chanel.Send.Send(result, num, SocketFlags.None); - } - catch (SocketException) - { - // Interrupted function call. 10004 - // An existing connection was forcibly closed by the remote host. 10054 - try - { - chanel.Send.Shutdown(SocketShutdown.Both); - } - catch { } - finally - { - chanel.Send.Close(); - } - try { - chanel.Receive.Shutdown(SocketShutdown.Both); + chanel.Send.Send(result, num, SocketFlags.None); } - catch { } - finally + catch (Exception) { - chanel.Receive.Close(); + closeSocket("Send Fail"); + break; } - break; } catch (Exception ex) { - Console.Write(ex.ToString()); - throw; + m_logger.LogCritical(ex, "致命异常"); + break; } } + + var interval = long.Parse(DateTime.Now.GetChinaTicks()) - long.Parse(m_msgId.Split('_')[0]); + m_logger?.LogDebug($"endSwap {m_msgId} 交互时常:{interval}ms"); + } + + private void closeSocket(string msg) + { + m_logger.LogDebug($"【closeSocket】:{msg}"); + + try + { + m_sockt1.Shutdown(SocketShutdown.Both); + } + catch (Exception) + { + } + finally + { + m_sockt1.Close(); + } + + try + { + m_sockt2.Shutdown(SocketShutdown.Both); + + } + catch (Exception) + { + } + finally + { + m_sockt2.Close(); + } + } public ISocketSwap BeforeSwap(Action fun) { + m_logger?.LogDebug($"BeforeSwap {m_msgId}"); + if (Swaped) { throw new Exception("BeforeSwap must be invoked before StartSwap!"); diff --git a/FastTunnel.Core/Utility/Extensions/DateTimeExtensions.cs b/FastTunnel.Core/Utility/Extensions/DateTimeExtensions.cs new file mode 100644 index 0000000..5ea7f58 --- /dev/null +++ b/FastTunnel.Core/Utility/Extensions/DateTimeExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FastTunnel.Core.Utility.Extensions +{ + public static class DateTimeExtensions + { + public static string GetChinaTicks(this DateTime dateTime) + { + // 北京时间相差8小时 + DateTime startTime = TimeZoneInfo.ConvertTime(new DateTime(1970, 1, 1, 8, 0, 0, 0), TimeZoneInfo.Local); + long t = (dateTime.Ticks - startTime.Ticks) / 10000; + return t.ToString(); + } + } +} diff --git a/addhost.bat b/addhost.bat index e296c31..b8a76c8 100644 --- a/addhost.bat +++ b/addhost.bat @@ -2,8 +2,8 @@ echo 127.0.0.1 test.cc >>C:\Windows\System32\drivers\etc\hosts echo 127.0.0.1 test.test.cc >>C:\Windows\System32\drivers\etc\hosts echo 127.0.0.1 test1.test.cc >>C:\Windows\System32\drivers\etc\hosts -echo 127.0.0.1 test111.test.cc >>C:\Windows\System32\drivers\etc\hosts -echo 127.0.0.1 test111.test.cc >>C:\Windows\System32\drivers\etc\hosts +echo 127.0.0.1 test2.test.cc >>C:\Windows\System32\drivers\etc\hosts +echo 127.0.0.1 test3.test.cc >>C:\Windows\System32\drivers\etc\hosts echo 127.0.0.1 www.abc.com >>C:\Windows\System32\drivers\etc\hosts pause \ No newline at end of file