diff --git a/AsyncHttpServer.cs b/AsyncHttpServer.cs new file mode 100644 index 0000000..3beab0d --- /dev/null +++ b/AsyncHttpServer.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using System.Xml.Linq; +using TouchSocket.Core; +using TouchSocket.Http; +using TouchSocket.Http.WebSockets; +using TouchSocket.Sockets; + + +namespace ForwardingServer +{ + public class AsyncHttpServer + { + public static HttpService httpservice = new HttpService(); + + public static async Task HttpMain() + { + await httpservice.SetupAsync(new TouchSocketConfig()//加载配置 + .SetListenIPHosts(7791) + .ConfigureContainer(a => + { + a.AddConsoleLogger(); + }) + .ConfigurePlugins(a => + { + a.Add(); + //default插件应该最后添加,其作用是 + //1、为找不到的路由返回404 + //2、处理 header 为Option的探视跨域请求。 + a.UseDefaultHttpServicePlugin(); + })); + await httpservice.StartAsync(); + + Console.WriteLine("HttpService:Run"); + } + + public class MyHttpPlug1 : PluginBase, IHttpPlugin + { + public async Task OnHttpRequest(IHttpSessionClient client, HttpContextEventArgs e) + { + #region HttpContext生命周期 + //var request = e.Context.Request;//http请求体 + var response = e.Context.Response;//http响应体 + #endregion + + var bodyString = await e.Context.Request.GetBodyAsync(); + + //获取路径 + var URL = e.Context.Request.URL; + + try + { + string dat; + DataRow[] rows = DATA.MachineTable.Select("Enterprise='/" + URL + "'"); + if (rows.Length > 0) + { + string? s_ = rows.First().Field("ID")!; + + if (s_ != null) + { + // var deserialized = JsonSerializer.Deserialize>(bodyString)!; + + // if (deserialized.TryGetValue("Terminal", out var val) && val != null) { } + // using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + + await AsyncTcpServer.service.SendAsync(s_, bodyString); + + DATA.Person deserializedPerson = JsonSerializer.Deserialize(bodyString)!; + + DATA.UserTable.Rows.Add(client.Id, client.IP, deserializedPerson.User, + "", deserializedPerson.Terminal, "", ""); + + // 创建一个 秒的延时任务 + Task delayTask = Task.Delay(15000); + // 创建一个监测任务,不断检查变量 + Task monitorTask = Task.Run(async () => + { + while (!(DATA.UserTable.Select("Terminal='" + deserializedPerson.Terminal + "'"). + First().Field("RDAT")!.Length > 1)) + { + await Task.Delay(500); + } + }); + Task winner = await Task.WhenAny(delayTask, monitorTask); + + DataRow[] dataRows = DATA.UserTable.Select("Terminal='" + deserializedPerson.Terminal + "'"); + if (winner == monitorTask) + { + dat = dataRows.First().Field("RDAT")!; + } + else { dat = "970"; } + foreach (DataRow row in dataRows) + { + DATA.UserTable.Rows.Remove(row); + } + } + else { dat = "999"; } + } + else + { + dat = "980"; + } + + e.Context.Response.Headers.Add("SUNLIGHT", "SUNLIGHT"); + e.Context.Response.SetStatus(200, "success"); + e.Context.Response.SetContent(Encoding.UTF8.GetBytes(dat.ToCharArray())); + await e.Context.Response.AnswerAsync(); + } + catch (TimeoutException) + { + Console.WriteLine("等待TCP服务端响应超时"); + } + catch (Exception ex) + {//错误 + Console.WriteLine("Http:" + ex.ToString()); + //client.SendAsync("Target instruction parsing error manager will close connection"); + } + + /* if (request.IsGet() && request.UrlEquals("/success")) + { + //直接响应文字 + await response + .SetStatus(200, "success") + .FromText("Success") + .AnswerAsync();//直接回应 + Console.WriteLine("处理/success"); + return; + } + + //无法处理,调用下一个插件 + await e.InvokeNext();*/ + } + } + + + + + + + + + + + + } +} diff --git a/AsyncTcpServer.cs b/AsyncTcpServer.cs new file mode 100644 index 0000000..ba0b347 --- /dev/null +++ b/AsyncTcpServer.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Security.Cryptography.Pkcs; +using System.Text; +using System.Text.Json; +using System.Windows.Markup; +using System.Xml.Linq; +using TouchSocket.Core; +using TouchSocket.Sockets; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace ForwardingServer +{ + public class AsyncTcpServer + { + public class Personm + { + public required string SERVEREnterprise { get; set; } + public required string SERVERMachineName { get; set; } + public required string SERVERNAME { get; set; } + public required string SERVERUSER { get; set; } + public required string SERRVERPASWORD { get; set; } + public required string MachineVer { get; set; } + } + public static TcpService service = new TcpService(); + public static async Task TcpMain() + { + //TcpService service = new TcpService(); + service.Connecting = (client, e) => { return EasyTask.CompletedTask; };//有客户端正在连接 + service.Connected = (client, e) => {return EasyTask.CompletedTask;};//有客户端成功连接 + service.Closing = (client, e) => {return EasyTask.CompletedTask; };//有客户端正在断开连接,只有当主动断开时才有效。 + service.Closed = (client, e) => { + //离线记录 + DataRow[] dat = DATA.MachineTable.Select("ID='"+client.Id+"'"); + foreach (DataRow row in dat) + { + DATA.MachineTable.Rows.Remove(row); + } + Console.WriteLine("NOT ID " + client.Id + " IP " + client.IP); + + return EasyTask.CompletedTask; + };//有客户端断开连接 + service.Received = (client, e) =>{ + string DAT = e.Memory.Span.ToString(Encoding.UTF8); + try + { + DataRow[] r_ = DATA.MachineTable.Select("ID='" + client.Id + "'"); + if (r_.Length > 0) + { + int? s_ = r_.First().Field("Start"); + + if (s_ == 30) + { + if (DAT.StartsWith("{") || DAT.StartsWith("[")) + { + DATA.Person deserializedPerson = JsonSerializer.Deserialize(DAT)!; + //转发逻辑 + var dr = DATA.UserTable.Select("Terminal='" + deserializedPerson.Terminal + "'"); + if (dr.Length > 0) + { + DataRow drEmployee = dr.First(); + drEmployee.BeginEdit(); + drEmployee["RDAT"] = DAT; + drEmployee.EndEdit(); + drEmployee.AcceptChanges(); + } + } + + } + } + else + { + Personm deserializedPerson = JsonSerializer.Deserialize(DAT)!; + DATA.MachineTable.Rows.Add(client.Id, client.IP, 30, "/" + deserializedPerson.SERVEREnterprise, + deserializedPerson.SERVERMachineName, deserializedPerson.MachineVer); + Console.WriteLine("LINK ID "+client.Id+" IP "+ client.IP+" DATA "+ DAT); + } + } + catch (Exception ex) + {//错误 + Console.WriteLine("Tcp:" + ex.ToString()); + } + + return EasyTask.CompletedTask; + }; + + + await service.SetupAsync(new TouchSocketConfig()//载入配置 + // .SetMaxBufferSize(1024 * 1024 * 100) + //.SetMinBufferSize(1024 * 1024) + .SetSingleStreamDataHandlingAdapter(() => new PeriodPackageAdapter())//以超时周期和包 + .SetListenIPHosts(new IPHost[] { new IPHost(7794), new IPHost(7795) })//同时监听两个地址 + .ConfigureContainer(a =>//容器的配置顺序应该在最前面 + { + }) + .ConfigurePlugins(a => + { + }) + ); + + await service.StartAsync();//启动 + + Console.WriteLine("TcpServer:Run"); + } + + } +} diff --git a/AsyncWebSocketServer.cs b/AsyncWebSocketServer.cs new file mode 100644 index 0000000..a201edd --- /dev/null +++ b/AsyncWebSocketServer.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; +using TouchSocket.Core; +using TouchSocket.Http; +using TouchSocket.Http.WebSockets; +using TouchSocket.Sockets; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace ForwardingServer +{ + public class AsyncWebSocketServer + { + + public static HttpService service = new HttpService(); + public static async Task WebSocketMain() + { + //var service = new HttpService(); + + var config = new TouchSocketConfig(); + config.SetListenIPHosts(7792) + .ConfigureContainer(a => + { + a.AddConsoleLogger(); + }) + .ConfigurePlugins(a => + { + //添加WebSocket功能 + a.UseWebSocket(options => + { + options.SetVerifyConnection(async (client, context) => + { + if (!context.Request.IsUpgrade()) + { + //如果不包含升级协议的header,就直接返回false。 + return false; + } + + // 在此处添加验证逻辑,例如:匹配特定的URL + if (true) // context.Request.UrlEquals("/ws")) + { + var url = context.Request.URL; + + return true; // 允许连接 + } + + //如果url不匹配,则可以直接拒绝。 + //await context.Response + //.SetStatus(403, "url不正确") + //.AnswerAsync(); + return false; + }); + + + }); + + + a.Add(); + a.Add(); + }); + + //加载配置 + await service.SetupAsync(config); + + //启动服务 + await service.StartAsync(); + + Console.WriteLine("WebSocketService:Run"); + } + + public async Task WebSocketSendAsync(string id,string dat) { + var clients = service.Clients; + foreach (var client in clients) + { + if (client.Protocol == Protocol.WebSocket)//先判断是不是websocket协议 + { + if (client.Id == id)//再按指定id发送,或者直接广播发送 + { + var webSocket = client.WebSocket; + await webSocket.SendAsync(dat); + } + } + } + } + + + private class MyWebSocketClosedPlugin : PluginBase, IWebSocketClosedPlugin + { + public async Task OnWebSocketClosed(IWebSocket webSocket, ClosedEventArgs e) + { + var ClientId = (webSocket as IIdClient)!.Id; + + } + } + private class MyWebSocketReceivePlugin : PluginBase, IWebSocketReceivedPlugin + { + public async Task OnWebSocketReceived(IWebSocket webSocket, WSDataFrameEventArgs e) + { + //处理接收的数据 + var dataFrame = e.DataFrame; + switch (dataFrame.Opcode) + { + case WSDataType.Cont: + //处理中继包 + break; + + case WSDataType.Text: + //处理文本包 + Console.WriteLine(dataFrame.ToText()); + break; + + case WSDataType.Binary: + //处理二进制包 + var data = dataFrame.PayloadData; + Console.WriteLine($"收到二进制数据,长度:{data.Length}"); + break; + + case WSDataType.Close: + //处理关闭包 + break; + + case WSDataType.Ping: + //处理Ping包 + break; + + case WSDataType.Pong: + //处理Pong包 + break; + + default: + //处理其他包 + break; + } + await e.InvokeNext(); + } + + } + + + } +} diff --git a/DATA.cs b/DATA.cs new file mode 100644 index 0000000..bed6775 --- /dev/null +++ b/DATA.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Text; + +namespace ForwardingServer +{ + public class DATA + { + public class Person + { + public required string User { get; set; } + public required string Password { get; set; } + public required string IP { get; set; } + public required string Terminal { get; set; } + public required string Dat { get; set; } + } + + public static DataTable MachineTable = new(); + public static DataTable UserTable = new(); + + public static void Data() + { + MachineTable.Columns.Add("ID", typeof(string)); + MachineTable.Columns.Add("IP", typeof(string)); + MachineTable.Columns.Add("Start", typeof(int)); + MachineTable.Columns.Add("Enterprise", typeof(string)); + MachineTable.Columns.Add("MachineName", typeof(string)); + MachineTable.Columns.Add("MachineVer", typeof(string)); + + + UserTable.Columns.Add("ID", typeof(string)); + UserTable.Columns.Add("IP", typeof(string)); + UserTable.Columns.Add("User", typeof(string)); + UserTable.Columns.Add("Enterprise", typeof(string)); + UserTable.Columns.Add("Terminal", typeof(string)); + UserTable.Columns.Add("MachineName", typeof(string)); + UserTable.Columns.Add("RDAT", typeof(string)); + } + } +} diff --git a/ForwardingServer.csproj b/ForwardingServer.csproj new file mode 100644 index 0000000..582c799 --- /dev/null +++ b/ForwardingServer.csproj @@ -0,0 +1,15 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + + diff --git a/ForwardingServer.slnx b/ForwardingServer.slnx new file mode 100644 index 0000000..62b667c --- /dev/null +++ b/ForwardingServer.slnx @@ -0,0 +1,3 @@ + + + diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..9de17e0 --- /dev/null +++ b/Program.cs @@ -0,0 +1,9 @@ +using ForwardingServer; + +DATA.Data(); + +await AsyncTcpServer.TcpMain(); +await AsyncHttpServer.HttpMain(); +//await AsyncWebSocketServer.WebSocketMain(); +Console.WriteLine("主程序启动,按任意键停止"); +await Task.Run(() =>Console.ReadKey()); \ No newline at end of file