From a289cb656204f1162b6adf5808790441d32cb26d Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Fri, 18 Oct 2024 16:47:32 +0800 Subject: [PATCH] =?UTF-8?q?standard2=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HaoYueNet.ClientNetwork.Standard2.dll | Bin 0 -> 34304 bytes .../HaoYueNet.ClientNetworkNet.Standard2.dll | Bin 21504 -> 0 bytes .../NoSugarNet.Adapter.csproj.user | 6 + NoSugarNet.ClientCli.Standard2/Config.cs | 73 + .../NoSugarNet.ClientCli.Standard2.csproj | 14 + NoSugarNet.ClientCli.Standard2/Program.cs | 77 + .../AppNoSugarNet.cs | 87 +- .../Common/Config.cs | 18 + .../Common/Helper.cs | 2 +- .../Common/ProtoBufHelper.cs | 2 +- .../Event/EEvent.cs | 2 +- .../Event/EventSystem.cs | 2 +- .../Manager/AppChat.cs | 8 +- ...ocalClient.cs => AppForwardLocalClient.cs} | 159 +- .../Manager/AppLogin.cs | 22 +- .../Manager/AppReverseLocalClient.cs | 365 +++++ .../Manager/LocalClient/LocalListener.cs | 505 ++++--- .../LocalClient/LocalListener_Source.cs | 522 +++---- .../Manager/LocalClient/LocalMsgQueuePool.cs | 96 +- .../Manager/LogManager.cs | 7 +- .../Manager/UserDataManager.cs | 7 +- NoSugarNet.ClientCore.Standard2/NetStatus.cs | 2 +- .../Network/NetMsg.cs | 2 +- .../Network/NetworkHelper.cs | 26 +- .../NoSugarNet.Adapter/BackwardLocalClient.cs | 113 ++ .../DataHelper/CompressAdapter.cs | 94 ++ .../DataHelper/CompressAdapterSelector.cs | 19 + .../ForwardLocalListener.cs | 347 +++++ .../NoSugarNet.Adapter/LocalMsgQueuePool.cs | 57 + .../NoSugarNet.ClientCore.Standard2.csproj | 4 +- .../PublishProfiles/FolderProfile.pubxml.user | 2 +- .../Protobuf/ProtobufNoSugar.cs | 1308 +++++------------ .../PublishProfiles/FolderProfile.pubxml | 14 + .../PublishProfiles/FolderProfile.pubxml.user | 10 + NoSugarNet.sln | 11 +- NosugarNetForUnity/Assets/MainUI.cs | 8 +- .../HaoYueNet.ClientNetwork.Standard2.dll | Bin 0 -> 34304 bytes ...aoYueNet.ClientNetwork.Standard2.dll.meta} | 2 +- .../HaoYueNet.ClientNetworkNet.Standard2.dll | Bin 21504 -> 0 bytes ...YueNet.ClientNetworkNet.Standard2.dll.meta | 33 - .../NoSugarNet.ClientCore.Standard2.dll | Bin 59904 -> 67072 bytes .../Assets/Plugins/NoSugarNet.DataHelper.dll | Bin 5632 -> 0 bytes .../NoSugarNet.ServerCli.csproj | 1 + 43 files changed, 2349 insertions(+), 1678 deletions(-) create mode 100644 Lib/NetLib_Standard2/HaoYueNet.ClientNetwork.Standard2.dll delete mode 100644 Lib/NetLib_Standard2/HaoYueNet.ClientNetworkNet.Standard2.dll create mode 100644 NoSugarNet.Adapter/NoSugarNet.Adapter.csproj.user create mode 100644 NoSugarNet.ClientCli.Standard2/Config.cs create mode 100644 NoSugarNet.ClientCli.Standard2/NoSugarNet.ClientCli.Standard2.csproj create mode 100644 NoSugarNet.ClientCli.Standard2/Program.cs create mode 100644 NoSugarNet.ClientCore.Standard2/Common/Config.cs rename NoSugarNet.ClientCore.Standard2/Manager/{AppLocalClient.cs => AppForwardLocalClient.cs} (62%) create mode 100644 NoSugarNet.ClientCore.Standard2/Manager/AppReverseLocalClient.cs create mode 100644 NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/BackwardLocalClient.cs create mode 100644 NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapter.cs create mode 100644 NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapterSelector.cs create mode 100644 NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/ForwardLocalListener.cs create mode 100644 NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/LocalMsgQueuePool.cs create mode 100644 NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml create mode 100644 NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml.user create mode 100644 NosugarNetForUnity/Assets/Plugins/HaoYueNet.ClientNetwork.Standard2.dll rename NosugarNetForUnity/Assets/Plugins/{NoSugarNet.DataHelper.dll.meta => HaoYueNet.ClientNetwork.Standard2.dll.meta} (93%) delete mode 100644 NosugarNetForUnity/Assets/Plugins/HaoYueNet.ClientNetworkNet.Standard2.dll delete mode 100644 NosugarNetForUnity/Assets/Plugins/HaoYueNet.ClientNetworkNet.Standard2.dll.meta delete mode 100644 NosugarNetForUnity/Assets/Plugins/NoSugarNet.DataHelper.dll diff --git a/Lib/NetLib_Standard2/HaoYueNet.ClientNetwork.Standard2.dll b/Lib/NetLib_Standard2/HaoYueNet.ClientNetwork.Standard2.dll new file mode 100644 index 0000000000000000000000000000000000000000..3802b84e5e2727cdf790b9e869fb721577dfbabb GIT binary patch literal 34304 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 V>Tjra%5PKupqBi*@;`tF{tps}IY9sb diff --git a/NoSugarNet.Adapter/NoSugarNet.Adapter.csproj.user b/NoSugarNet.Adapter/NoSugarNet.Adapter.csproj.user new file mode 100644 index 0000000..beee134 --- /dev/null +++ b/NoSugarNet.Adapter/NoSugarNet.Adapter.csproj.user @@ -0,0 +1,6 @@ + + + + <_LastSelectedProfileId>F:\Sin365\NoSugarNet\NoSugarNet.Adapter\Properties\PublishProfiles\FolderProfile.pubxml + + \ No newline at end of file diff --git a/NoSugarNet.ClientCli.Standard2/Config.cs b/NoSugarNet.ClientCli.Standard2/Config.cs new file mode 100644 index 0000000..4770d4e --- /dev/null +++ b/NoSugarNet.ClientCli.Standard2/Config.cs @@ -0,0 +1,73 @@ +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Unicode; + +namespace NoSugarNet.ClientCli +{ + + public class ConfigDataModel + { + public string ServerIP { get; set; } + public int ServerPort { get; set; } + public int CompressAdapterType { get; set; } + public List TunnelList { get; set; } + } + + public class ConfigDataModel_Single + { + public string LocalTargetIP { get; set; } + public int LocalTargetPort { get; set; } + public int RemoteLocalPort { get; set; } + } + + public static class Config + { + public static ConfigDataModel cfg; + public static bool LoadConfig() + { + try + { + string path = System.Environment.CurrentDirectory + "//config.cfg"; + if (!File.Exists(path)) + { + ConfigDataModel sampleCfg = new ConfigDataModel + { + ServerIP = "127.0.0.1", + ServerPort = 1000, + TunnelList = new List() + { + new ConfigDataModel_Single(){ LocalTargetIP = "127.0.0.1",LocalTargetPort=3389,RemoteLocalPort = 20001}, + new ConfigDataModel_Single(){ LocalTargetIP = "127.0.0.1",LocalTargetPort=3389,RemoteLocalPort = 20002} + } + }; + + string jsonString = JsonSerializer.Serialize(sampleCfg, new JsonSerializerOptions() + { + // 整齐打印 + WriteIndented = true, + //重新编码,解决中文乱码问题 + Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) + }); + System.IO.File.WriteAllText(path, jsonString, Encoding.UTF8); + + Console.WriteLine("未找到配置,已生成模板,请浏览" + path); + return false; + } + StreamReader sr = new StreamReader(path, Encoding.Default); + String jsonstr = sr.ReadToEnd(); + cfg = JsonSerializer.Deserialize(jsonstr); + sr.Close(); + if (cfg?.TunnelList.Count > 0) + return true; + else + return false; + } + catch (Exception ex) + { + Console.WriteLine("配置文件异常:" + ex.ToString()); + return false; + } + } + } +} diff --git a/NoSugarNet.ClientCli.Standard2/NoSugarNet.ClientCli.Standard2.csproj b/NoSugarNet.ClientCli.Standard2/NoSugarNet.ClientCli.Standard2.csproj new file mode 100644 index 0000000..5360dad --- /dev/null +++ b/NoSugarNet.ClientCli.Standard2/NoSugarNet.ClientCli.Standard2.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/NoSugarNet.ClientCli.Standard2/Program.cs b/NoSugarNet.ClientCli.Standard2/Program.cs new file mode 100644 index 0000000..99aba84 --- /dev/null +++ b/NoSugarNet.ClientCli.Standard2/Program.cs @@ -0,0 +1,77 @@ +using NoSugarNet.ClientCore; +using NoSugarNet.ClientCore.Common; + +namespace NoSugarNet.ClientCli.Standard2 +{ + internal class Program + { + static string Title = "NoSugarNetClient"; + static void Main(string[] args) + { + if (!Config.LoadConfig()) + { + Console.WriteLine("配置文件错误"); + Console.ReadLine(); + return; + } + + AppNoSugarNet.OnUpdateStatus += OnUpdateStatus; + + Dictionary dictTunnel = new Dictionary(); + for (int i = 0; i < Config.cfg.TunnelList.Count; i++) + { + ConfigDataModel_Single cfgSingle = Config.cfg.TunnelList[i]; + dictTunnel[(byte)i] = new TunnelClientData() + { + TunnelId = (byte)i, + LocalTargetIP = cfgSingle.LocalTargetIP, + LocalTargetPort = (ushort)cfgSingle.LocalTargetPort, + RemoteLocalPort = (ushort)cfgSingle.RemoteLocalPort, + }; + } + + AppNoSugarNet.Init(dictTunnel, Config.cfg.CompressAdapterType, OnNoSugarNetLog); + AppNoSugarNet.Connect(Config.cfg.ServerIP, Config.cfg.ServerPort); + while (true) + { + string CommandStr = Console.ReadLine(); + string Command = ""; + Command = ((CommandStr.IndexOf(" ") <= 0) ? CommandStr : CommandStr.Substring(0, CommandStr.IndexOf(" "))); + string[] CmdArr = CommandStr.Split(' '); + switch (Command) + { + case "con": + AppNoSugarNet.Connect(Config.cfg.ServerIP, Config.cfg.ServerPort); + break; + case "tlist": + AppNoSugarNet.forwardlocal.GetClientCount(out int ClientUserCount, out int TunnelCount); + Console.WriteLine($"GetClientCount->{ClientUserCount} TunnelCount->{TunnelCount}"); + + AppNoSugarNet.forwardlocal.GetClientDebugInfo(); + break; + case "stop": + AppNoSugarNet.Close(); + break; + default: + break; + } + } + } + static void OnUpdateStatus(NetStatus Forward_NetStatus, NetStatus Reverse_NetStatus) + { + string info = $"Forward: t:{Forward_NetStatus.TunnelCount} r:{ConvertBytesToKilobytes(Forward_NetStatus.srcReciveSecSpeed)}K/s|{ConvertBytesToKilobytes(Forward_NetStatus.tReciveSecSpeed)}K/s s: {ConvertBytesToKilobytes(Forward_NetStatus.srcSendSecSpeed)}K/s|{ConvertBytesToKilobytes(Forward_NetStatus.tSendSecSpeed)}K/s" + + $"| Reverse t:{Reverse_NetStatus.TunnelCount} r:{ConvertBytesToKilobytes(Reverse_NetStatus.srcReciveSecSpeed)}K/s|{ConvertBytesToKilobytes(Reverse_NetStatus.tReciveSecSpeed)}K/s s: {ConvertBytesToKilobytes(Reverse_NetStatus.srcSendSecSpeed)}K/s|{ConvertBytesToKilobytes(Reverse_NetStatus.tSendSecSpeed)}K/s"; + Console.Title = Title + info; + Console.WriteLine(info); + } + static string ConvertBytesToKilobytes(long bytes) + { + return Math.Round((double)bytes / 1024, 2).ToString("F2"); + } + static void OnNoSugarNetLog(int LogLevel, string msg) + { + Console.WriteLine(msg); + } + + } +} \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/AppNoSugarNet.cs b/NoSugarNet.ClientCore.Standard2/AppNoSugarNet.cs index a6e4847..b76ea66 100644 --- a/NoSugarNet.ClientCore.Standard2/AppNoSugarNet.cs +++ b/NoSugarNet.ClientCore.Standard2/AppNoSugarNet.cs @@ -1,9 +1,12 @@ -using NoSugarNet.ClientCoreNet.Standard2.Manager; -using NoSugarNet.ClientCoreNet.Standard2.Network; +using NoSugarNet.Adapter.DataHelper; +using NoSugarNet.ClientCore.Common; +using NoSugarNet.ClientCore.Manager; +using NoSugarNet.ClientCore.Network; using ServerCore.Manager; -using static NoSugarNet.ClientCoreNet.Standard2.Manager.LogManager; +using System.Collections.Generic; +using static NoSugarNet.ClientCore.Manager.LogManager; -namespace NoSugarNet.ClientCoreNet.Standard2 +namespace NoSugarNet.ClientCore { public class AppNoSugarNet { @@ -15,28 +18,35 @@ namespace NoSugarNet.ClientCoreNet.Standard2 public static NetworkHelper networkHelper; public static AppLogin login; public static AppChat chat; - public static AppLocalClient local; + public static AppForwardLocalClient forwardlocal; + public static AppReverseLocalClient reverselocal; public static UserDataManager user; public static System.Timers.Timer _SpeedCheckTimeTimer;//速度检测计时器 public static int TimerInterval = 1000;//计时器间隔 - static NetStatus netStatus; + static NetStatus Forward_NetStatus; + static NetStatus Reverse_NetStatus; #region 委托和事件 - public delegate void OnUpdateStatusHandler(NetStatus Status); + public delegate void OnUpdateStatusHandler(NetStatus ForwardStatus, NetStatus ReverseStatus); public static event OnUpdateStatusHandler OnUpdateStatus; #endregion - public static void Init(OnLogHandler onLog = null) + public static void Init(Dictionary cfgs, int compressAdapterType = 0,OnLogHandler onLog = null) { + Config.cfgs = cfgs; + Config.compressAdapterType = (E_CompressAdapter)compressAdapterType; + log = new LogManager(); if(onLog != null) LogManager.OnLog += onLog; networkHelper = new NetworkHelper(); login = new AppLogin(); chat = new AppChat(); - local = new AppLocalClient(); + forwardlocal = new AppForwardLocalClient(); + reverselocal = new AppReverseLocalClient(Config.compressAdapterType); user = new UserDataManager(); - netStatus = new NetStatus(); + Forward_NetStatus = new NetStatus(); + Reverse_NetStatus = new NetStatus(); _SpeedCheckTimeTimer = new System.Timers.Timer(); _SpeedCheckTimeTimer.Interval = TimerInterval; _SpeedCheckTimeTimer.Elapsed += Checktimer_Elapsed; @@ -53,7 +63,7 @@ namespace NoSugarNet.ClientCoreNet.Standard2 public static void Close() { - local.StopAll(); + forwardlocal.StopAll(); networkHelper.CloseConntect(); AppNoSugarNet.log.Info("停止"); _SpeedCheckTimeTimer.Enabled = false; @@ -61,24 +71,45 @@ namespace NoSugarNet.ClientCoreNet.Standard2 static void Checktimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { - local.GetCurrLenght(out long resultReciveAllLenght, out long resultSendAllLenght); - local.GetClientCount(out int ClientUserCount, out int TunnelCount); - - NetStatus resutnetStatus = new NetStatus() { - TunnelCount = TunnelCount, - ClientUserCount = ClientUserCount, - srcSendAllLenght = resultSendAllLenght, - srcReciveAllLenght = resultReciveAllLenght, - srcReciveSecSpeed = (resultReciveAllLenght - netStatus.srcReciveAllLenght) / (TimerInterval / 1000), - srcSendSecSpeed = (resultSendAllLenght - netStatus.srcSendAllLenght) / (TimerInterval / 1000), - tSendAllLenght = local.tSendAllLenght, - tReciveAllLenght = local.tReciveAllLenght, - tSendSecSpeed = (local.tSendAllLenght - netStatus.tSendAllLenght) / (TimerInterval / 1000), - tReciveSecSpeed = (local.tReciveAllLenght - netStatus.tReciveAllLenght) / (TimerInterval / 1000), - }; - netStatus = resutnetStatus; - OnUpdateStatus?.Invoke(resutnetStatus); + forwardlocal.GetCurrLenght(out long resultReciveAllLenght, out long resultSendAllLenght); + forwardlocal.GetClientCount(out int ClientUserCount, out int TunnelCount); + NetStatus resutnetStatus = new NetStatus() + { + TunnelCount = TunnelCount, + ClientUserCount = ClientUserCount, + srcSendAllLenght = resultSendAllLenght, + srcReciveAllLenght = resultReciveAllLenght, + srcReciveSecSpeed = (resultReciveAllLenght - Forward_NetStatus.srcReciveAllLenght) / (TimerInterval / 1000), + srcSendSecSpeed = (resultSendAllLenght - Forward_NetStatus.srcSendAllLenght) / (TimerInterval / 1000), + tSendAllLenght = forwardlocal.tSendAllLenght, + tReciveAllLenght = forwardlocal.tReciveAllLenght, + tSendSecSpeed = (forwardlocal.tSendAllLenght - Forward_NetStatus.tSendAllLenght) / (TimerInterval / 1000), + tReciveSecSpeed = (forwardlocal.tReciveAllLenght - Forward_NetStatus.tReciveAllLenght) / (TimerInterval / 1000), + }; + Forward_NetStatus = resutnetStatus; + } + + { + reverselocal.GetCurrLenght(out long resultReciveAllLenght, out long resultSendAllLenght); + reverselocal.GetClientCount(out int ClientUserCount, out int TunnelCount); + NetStatus resutnetStatus = new NetStatus() + { + TunnelCount = TunnelCount, + ClientUserCount = ClientUserCount, + srcSendAllLenght = resultSendAllLenght, + srcReciveAllLenght = resultReciveAllLenght, + srcReciveSecSpeed = (resultReciveAllLenght - Reverse_NetStatus.srcReciveAllLenght) / (TimerInterval / 1000), + srcSendSecSpeed = (resultSendAllLenght - Reverse_NetStatus.srcSendAllLenght) / (TimerInterval / 1000), + tSendAllLenght = reverselocal.tSendAllLenght, + tReciveAllLenght = reverselocal.tReciveAllLenght, + tSendSecSpeed = (reverselocal.tSendAllLenght - Reverse_NetStatus.tSendAllLenght) / (TimerInterval / 1000), + tReciveSecSpeed = (reverselocal.tReciveAllLenght - Reverse_NetStatus.tReciveAllLenght) / (TimerInterval / 1000), + }; + Reverse_NetStatus = resutnetStatus; + } + + OnUpdateStatus?.Invoke(Forward_NetStatus , Reverse_NetStatus); } } } \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/Common/Config.cs b/NoSugarNet.ClientCore.Standard2/Common/Config.cs new file mode 100644 index 0000000..d58e3ab --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/Common/Config.cs @@ -0,0 +1,18 @@ +using NoSugarNet.Adapter.DataHelper; +using System.Collections.Generic; + +namespace NoSugarNet.ClientCore.Common +{ + public struct TunnelClientData + { + public byte TunnelId; + public string LocalTargetIP; + public ushort LocalTargetPort; + public ushort RemoteLocalPort; + } + public static class Config + { + public static Dictionary cfgs = new Dictionary(); + public static E_CompressAdapter compressAdapterType; + } +} diff --git a/NoSugarNet.ClientCore.Standard2/Common/Helper.cs b/NoSugarNet.ClientCore.Standard2/Common/Helper.cs index 8daba3e..e1239ed 100644 --- a/NoSugarNet.ClientCore.Standard2/Common/Helper.cs +++ b/NoSugarNet.ClientCore.Standard2/Common/Helper.cs @@ -1,6 +1,6 @@ using System; -namespace NoSugarNet.ClientCoreNet.Standard2.Common +namespace NoSugarNet.ClientCore.Common { public static class Helper { diff --git a/NoSugarNet.ClientCore.Standard2/Common/ProtoBufHelper.cs b/NoSugarNet.ClientCore.Standard2/Common/ProtoBufHelper.cs index 3c229bc..ab2d64f 100644 --- a/NoSugarNet.ClientCore.Standard2/Common/ProtoBufHelper.cs +++ b/NoSugarNet.ClientCore.Standard2/Common/ProtoBufHelper.cs @@ -1,7 +1,7 @@ using Google.Protobuf; using System; -namespace NoSugarNet.ClientCoreNet.Standard2.Common +namespace NoSugarNet.ClientCore.Common { public static class ProtoBufHelper { diff --git a/NoSugarNet.ClientCore.Standard2/Event/EEvent.cs b/NoSugarNet.ClientCore.Standard2/Event/EEvent.cs index 5e1e9f4..71fc2a7 100644 --- a/NoSugarNet.ClientCore.Standard2/Event/EEvent.cs +++ b/NoSugarNet.ClientCore.Standard2/Event/EEvent.cs @@ -1,4 +1,4 @@ -namespace NoSugarNet.ClientCoreNet.Standard2.Event +namespace NoSugarNet.ClientCore.Event { public enum EEvent { diff --git a/NoSugarNet.ClientCore.Standard2/Event/EventSystem.cs b/NoSugarNet.ClientCore.Standard2/Event/EventSystem.cs index b4f4d92..a9761ec 100644 --- a/NoSugarNet.ClientCore.Standard2/Event/EventSystem.cs +++ b/NoSugarNet.ClientCore.Standard2/Event/EventSystem.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace NoSugarNet.ClientCoreNet.Standard2.Event +namespace NoSugarNet.ClientCore.Event { public class EventData { diff --git a/NoSugarNet.ClientCore.Standard2/Manager/AppChat.cs b/NoSugarNet.ClientCore.Standard2/Manager/AppChat.cs index 68b1635..e1ea8e1 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/AppChat.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/AppChat.cs @@ -1,9 +1,9 @@ using AxibugProtobuf; -using NoSugarNet.ClientCoreNet.Standard2.Common; -using NoSugarNet.ClientCoreNet.Standard2.Event; -using NoSugarNet.ClientCoreNet.Standard2.Network; +using NoSugarNet.ClientCore.Common; +using NoSugarNet.ClientCore.Event; +using NoSugarNet.ClientCore.Network; -namespace NoSugarNet.ClientCoreNet.Standard2.Manager +namespace NoSugarNet.ClientCore.Manager { public class AppChat { diff --git a/NoSugarNet.ClientCore.Standard2/Manager/AppLocalClient.cs b/NoSugarNet.ClientCore.Standard2/Manager/AppForwardLocalClient.cs similarity index 62% rename from NoSugarNet.ClientCore.Standard2/Manager/AppLocalClient.cs rename to NoSugarNet.ClientCore.Standard2/Manager/AppForwardLocalClient.cs index 1324112..2a24270 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/AppLocalClient.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/AppForwardLocalClient.cs @@ -1,34 +1,32 @@ using AxibugProtobuf; using Google.Protobuf; -using NoSugarNet.ClientCoreNet.Standard2; -using NoSugarNet.ClientCoreNet.Standard2.Common; -using NoSugarNet.ClientCoreNet.Standard2.Network; -using NoSugarNet.DataHelper; +using NoSugarNet.Adapter; +using NoSugarNet.Adapter.DataHelper; +using NoSugarNet.ClientCore; +using NoSugarNet.ClientCore.Common; +using NoSugarNet.ClientCore.Network; using System; using System.Collections.Generic; using System.Linq; -using System.Net; namespace ServerCore.Manager { - public class AppLocalClient + public class AppForwardLocalClient { Dictionary mDictTunnelID2Cfg = new Dictionary(); - Dictionary mDictTunnelID2Listeners = new Dictionary(); - CompressAdapter mCompressAdapter; - E_CompressAdapter compressAdapterType; - public LocalMsgQueuePool _localMsgPool = new LocalMsgQueuePool(1000); + Dictionary mDictTunnelID2Listeners = new Dictionary(); + NoSugarNet.Adapter.DataHelper.E_CompressAdapter compressAdapterType; public long tReciveAllLenght { get; private set; } public long tSendAllLenght { get; private set; } - public AppLocalClient() + public AppForwardLocalClient() { //注册网络消息 - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdCfgs, Recive_CmdCfgs); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CConnect, Recive_TunnelS2CConnect); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CDisconnect, Recive_TunnelS2CDisconnect); - NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CData, Recive_TunnelS2CData); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdServerCfgs, Recive_CmdCfgs); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CForwardConnect, Recive_TunnelS2CConnect); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CForwardDisconnect, Recive_TunnelS2CDisconnect); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CForwardData, Recive_TunnelS2CData); } public void GetCurrLenght(out long resultReciveAllLenght, out long resultSendAllLenght) @@ -51,20 +49,40 @@ namespace ServerCore.Manager ClientUserCount = mDictTunnelID2Listeners.Count; } + public void GetClientDebugInfo() + { + AppNoSugarNet.log.Debug($"------------ mDictTunnelID2Listeners {mDictTunnelID2Listeners.Count} ------------"); + lock (mDictTunnelID2Listeners) + { + foreach (var item in mDictTunnelID2Listeners) + { + var cinfo = item.Value.GetDictIdx2LocalClientInfo(); + AppNoSugarNet.log.Debug($"----- TunnelID {item.Key} ObjcurrSeed->{item.Value.currSeed} ClientList->{item.Value.ClientList.Count} Idx2LocalClient->{cinfo.Count} -----"); + + foreach (var c in cinfo) + { + AppNoSugarNet.log.Debug($"----- Idx {c.Key} bRemoteConnect->{c.Value.bRemoteConnect} msgQueue.Count->{c.Value.msgQueue.Count} -----"); + } + } + } + } + /// /// 初始化连接,先获取到配置 /// void InitListenerMode() { AppNoSugarNet.log.Info("初始化压缩适配器" + compressAdapterType); - //初始化压缩适配器,代表压缩类型 - mCompressAdapter = new CompressAdapter(compressAdapterType); + ////初始化压缩适配器,代表压缩类型 + //mCompressAdapter = new NoSugarNet.Adapter.DataHelper.CompressAdapter(compressAdapterType); foreach (var cfg in mDictTunnelID2Cfg) { - LocalListener listener = new LocalListener(256, 1024, cfg.Key); + ForwardLocalListener listener = new ForwardLocalListener(256, 1024, cfg.Key,AppNoSugarNet.user.userdata.UID); AppNoSugarNet.log.Info($"开始监听配置 Tunnel:{cfg.Key},Port:{cfg.Value.Port}"); - listener.Init(); - listener.Start(new IPEndPoint(IPAddress.Any.Address, (int)cfg.Value.Port)); + listener.BandEvent(AppNoSugarNet.log.Log, OnClientLocalConnect, OnClientLocalDisconnect, OnClientTunnelDataCallBack); + listener.StartListener((uint)cfg.Value.Port); + //listener.Init(); + //listener.Start(new IPEndPoint(IPAddress.Any.Address, (int)cfg.Value.Port)); //listener.Init((int)cfg.Value.Port); AddLocalListener(listener); } @@ -77,7 +95,7 @@ namespace ServerCore.Manager /// /// /// - void AddLocalListener(LocalListener _listener) + void AddLocalListener(ForwardLocalListener _listener) { lock (mDictTunnelID2Listeners) { @@ -89,7 +107,7 @@ namespace ServerCore.Manager /// /// /// - void RemoveLocalListener(LocalListener _listener) + void RemoveLocalListener(ForwardLocalListener _listener) { lock (mDictTunnelID2Listeners) { @@ -99,7 +117,7 @@ namespace ServerCore.Manager } } } - bool GetLocalListener(byte tunnelId,out LocalListener _listener) + bool GetLocalListener(byte tunnelId,out ForwardLocalListener _listener) { _listener = null; if (!mDictTunnelID2Listeners.ContainsKey(tunnelId)) @@ -115,11 +133,13 @@ namespace ServerCore.Manager byte[] keys = mDictTunnelID2Listeners.Keys.ToArray(); for (int i = 0; i < keys.Length; i++) { - LocalListener _listener = mDictTunnelID2Listeners[keys[i]]; - _listener.StopAll(); + ForwardLocalListener _listener = mDictTunnelID2Listeners[keys[i]]; + _listener.StopAllLocalClient(); + _listener.StopWithClear(); //_listener.Stop(); RemoveLocalListener(_listener); } + mDictTunnelID2Listeners.Clear(); } } #endregion @@ -127,7 +147,7 @@ namespace ServerCore.Manager #region 解析服务端下行数据 public void Recive_CmdCfgs(byte[] reqData) { - AppNoSugarNet.log.Debug("Recive_CmdCfgs"); + AppNoSugarNet.log.Debug("Forward->Recive_CmdCfgs"); Protobuf_Cfgs msg = ProtoBufHelper.DeSerizlize(reqData); for (int i = 0;i < msg.Cfgs.Count;i++) @@ -135,29 +155,28 @@ namespace ServerCore.Manager Protobuf_Cfgs_Single cfg = msg.Cfgs[i]; mDictTunnelID2Cfg[(byte)cfg.TunnelID] = cfg; } - compressAdapterType = (E_CompressAdapter)msg.CompressAdapterType; + compressAdapterType = (NoSugarNet.Adapter.DataHelper.E_CompressAdapter)msg.CompressAdapterType; InitListenerMode(); } public void Recive_TunnelS2CConnect(byte[] reqData) { - AppNoSugarNet.log.Debug("Recive_TunnelS2CConnect"); - Protobuf_S2C_Connect msg = ProtoBufHelper.DeSerizlize(reqData); + AppNoSugarNet.log.Debug("Forward->Recive_TunnelS2CConnect"); + Protobuf_Tunnel_Connect msg = ProtoBufHelper.DeSerizlize(reqData); if(msg.Connected == 1) - OnServerLocalConnect((byte)msg.TunnelID,(byte)msg.Idx); + OnRemoteLocalConnect((byte)msg.TunnelID,(byte)msg.Idx); else - OnServerLocalDisconnect((byte)msg.TunnelID, (byte)msg.Idx); + OnRemoteLocalDisconnect((byte)msg.TunnelID, (byte)msg.Idx); } public void Recive_TunnelS2CDisconnect(byte[] reqData) { - AppNoSugarNet.log.Debug("Recive_TunnelS2CDisconnect"); - Protobuf_S2C_Disconnect msg = ProtoBufHelper.DeSerizlize(reqData); - OnServerLocalDisconnect((byte)msg.TunnelID,(byte)msg.Idx); + AppNoSugarNet.log.Debug("Forward->Recive_TunnelS2CDisconnect"); + Protobuf_Tunnel_Disconnect msg = ProtoBufHelper.DeSerizlize(reqData); + OnRemoteLocalDisconnect((byte)msg.TunnelID,(byte)msg.Idx); } public void Recive_TunnelS2CData(byte[] reqData) { - //AppNoSugarNet.log.Debug("Recive_TunnelS2CData"); - Protobuf_S2C_DATA msg = ProtoBufHelper.DeSerizlize(reqData); - OnServerLocalDataCallBack((byte)msg.TunnelID,(byte)msg.Idx, msg.HunterNetCoreData.ToArray()); + Protobuf_Tunnel_DATA msg = ProtoBufHelper.DeSerizlize(reqData); + OnRemoteLocalDataCallBack((byte)msg.TunnelID,(byte)msg.Idx, msg.HunterNetCoreData.ToArray()); } #endregion @@ -167,51 +186,51 @@ namespace ServerCore.Manager /// /// /// - public void OnClientLocalConnect(byte tunnelId,byte _Idx) + public void OnClientLocalConnect(long UID, byte tunnelId,byte _Idx) { - AppNoSugarNet.log.Debug($"OnClientLocalConnect {tunnelId},{_Idx}"); + AppNoSugarNet.log.Debug($"Forward->OnClientLocalConnect {tunnelId},{_Idx}"); if (!mDictTunnelID2Cfg.ContainsKey(tunnelId)) return; - byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_C2S_Connect() + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_Connect() { TunnelID = tunnelId, Idx = _Idx, }); //告知给服务端,来自客户端本地的连接建立 - AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SConnect, respData); + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SForwardConnect, respData); } /// /// 当客户端本地端口连接断开 /// /// /// - public void OnClientLocalDisconnect(byte tunnelId, byte _Idx) + public void OnClientLocalDisconnect(long UID, byte tunnelId, byte _Idx) { - AppNoSugarNet.log.Debug($"OnClientLocalDisconnect {tunnelId},{_Idx}"); + AppNoSugarNet.log.Debug($"Forward->OnClientLocalDisconnect {tunnelId},{_Idx}"); //隧道ID定位投递服务端本地连接 if (!mDictTunnelID2Cfg.ContainsKey(tunnelId)) return; - byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_C2S_Disconnect() + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_Disconnect() { TunnelID = tunnelId, Idx= _Idx, }); //告知给服务端,来自客户端本地的连接断开 - AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SDisconnect, respData); + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SForwardDisconnect, respData); } /// /// 当服务端本地端口连接 /// /// - public void OnServerLocalConnect(byte tunnelId,byte Idx) + public void OnRemoteLocalConnect(byte tunnelId,byte Idx) { - AppNoSugarNet.log.Debug($"OnServerLocalConnect {tunnelId},{Idx}"); - if (!GetLocalListener(tunnelId, out LocalListener _listener)) + AppNoSugarNet.log.Debug($"Forward->OnRemoteLocalConnect {tunnelId},{Idx}"); + if (!GetLocalListener(tunnelId, out ForwardLocalListener _listener)) return; //维护状态 _listener.SetRemoteConnectd(Idx, true); @@ -221,9 +240,9 @@ namespace ServerCore.Manager { IdxWithMsg msg = msglist[i]; //投递给服务端,来自客户端本地的连接数据 - AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SData, msg.data); + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SForwardData, msg.data); //发送后回收 - AppNoSugarNet.local._localMsgPool.Enqueue(msg); + MsgQueuePool._MsgPool.Enqueue(msg); } } } @@ -232,10 +251,10 @@ namespace ServerCore.Manager /// /// /// - public void OnServerLocalDisconnect(byte tunnelId, byte Idx) + public void OnRemoteLocalDisconnect(byte tunnelId, byte Idx) { - AppNoSugarNet.log.Debug($"OnServerLocalDisconnect {tunnelId},{Idx}"); - if (!GetLocalListener(tunnelId, out LocalListener _listener)) + AppNoSugarNet.log.Debug($"Forward->OnRemoteLocalDisconnect {tunnelId},{Idx}"); + if (!GetLocalListener(tunnelId, out ForwardLocalListener _listener)) return; _listener.SetRemoteConnectd(Idx,false); _listener.CloseConnectByIdx(Idx); @@ -249,15 +268,15 @@ namespace ServerCore.Manager /// /// /// - public void OnServerLocalDataCallBack(byte tunnelId,byte Idx, byte[] data) + public void OnRemoteLocalDataCallBack(byte tunnelId,byte Idx, byte[] data) { - //AppNoSugarNet.log.Info($"OnServerLocalDataCallBack {tunnelId},{Idx},Data长度:{data.Length}"); - if (!GetLocalListener(tunnelId, out LocalListener _listener)) + //AppNoSugarNet.log.Info($"OnRemoteLocalDataCallBack {tunnelId},{Idx},Data长度:{data.Length}"); + if (!GetLocalListener(tunnelId, out ForwardLocalListener _listener)) return; //记录压缩前数据长度 tReciveAllLenght += data.Length; //解压 - data = mCompressAdapter.Decompress(data); + data = CompressAdapterSelector.Adapter(compressAdapterType).Decompress(data); _listener.SendSocketByIdx(Idx,data); } /// @@ -266,16 +285,16 @@ namespace ServerCore.Manager /// /// /// - public void OnClientTunnelDataCallBack(byte tunnelId,byte Idx, byte[] data) + public void OnClientTunnelDataCallBack(long UID, byte tunnelId,byte Idx, byte[] data) { - //AppNoSugarNet.log.Info($"OnClientTunnelDataCallBack {tunnelId},{Idx}"); + //AppNoSugarNet.log.Info($"OnClientTunnelDataCallBack {tunnelId},{Idx} data.Length->{data.Length}"); int SlienLenght = 1000; //判断数据量大时分包 if (data.Length > SlienLenght) { - byte[] tempSpan = data; - byte[] tempSpanSlien = null; + Span tempSpan = data; + Span tempSpanSlien = null; int PageCount = (int)(data.Length / SlienLenght); if (data.Length % SlienLenght > 0) { @@ -284,21 +303,13 @@ namespace ServerCore.Manager for (int i = 0; i < PageCount; i++) { - tempSpanSlien = new byte[SlienLenght]; int StartIdx = i * SlienLenght; if (i != PageCount - 1)//不是最后一个包 - Array.Copy(tempSpan, StartIdx, tempSpanSlien, 0, SlienLenght); - else//最后一个 - Array.Copy(tempSpan, StartIdx, tempSpanSlien, 0, tempSpanSlien.Length - StartIdx); - - SendDataToRemote(tunnelId, Idx, tempSpanSlien); - - /*if (i != PageCount - 1)//不是最后一个包 tempSpanSlien = tempSpan.Slice(StartIdx, SlienLenght); else//最后一个 tempSpanSlien = tempSpan.Slice(StartIdx); - SendDataToRemote(tunnelId, Idx, tempSpanSlien.ToArray());*/ + SendDataToRemote(tunnelId, Idx, tempSpanSlien.ToArray()); } return; } @@ -308,18 +319,18 @@ namespace ServerCore.Manager void SendDataToRemote(byte tunnelId, byte Idx, byte[] data) { //压缩 - data = mCompressAdapter.Compress(data); + data = CompressAdapterSelector.Adapter(compressAdapterType).Compress(data); //记录压缩后数据长度 tSendAllLenght += data.Length; - byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_C2S_DATA() + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_DATA() { TunnelID = tunnelId, Idx = Idx, HunterNetCoreData = ByteString.CopyFrom(data) }); - if (!GetLocalListener(tunnelId, out LocalListener _listener)) + if (!GetLocalListener(tunnelId, out ForwardLocalListener _listener)) return; //远程未连接,添加到缓存 @@ -329,7 +340,7 @@ namespace ServerCore.Manager return; } //投递给服务端,来自客户端本地的连接数据 - AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SData, respData); + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SForwardData, respData); } #endregion diff --git a/NoSugarNet.ClientCore.Standard2/Manager/AppLogin.cs b/NoSugarNet.ClientCore.Standard2/Manager/AppLogin.cs index d9684d3..2be3d30 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/AppLogin.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/AppLogin.cs @@ -1,21 +1,29 @@ using AxibugProtobuf; -using NoSugarNet.ClientCoreNet.Standard2.Common; -using NoSugarNet.ClientCoreNet.Standard2.Network; +using NoSugarNet.ClientCore.Common; +using NoSugarNet.ClientCore.Network; +using System; -namespace NoSugarNet.ClientCoreNet.Standard2.Manager +namespace NoSugarNet.ClientCore.Manager { public class AppLogin { + static string LastLoginGuid = ""; public AppLogin() { NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdLogin, RecvLoginMsg); } - public void Login(string Account) + + public void Login() { + AppNoSugarNet.log.Debug("-->Login"); + if(string.IsNullOrEmpty(LastLoginGuid)) + LastLoginGuid = Guid.NewGuid().ToString(); + + AppNoSugarNet.user.userdata.Account = LastLoginGuid; Protobuf_Login msg = new Protobuf_Login() { LoginType = 0, - Account = Account, + Account = AppNoSugarNet.user.userdata.Account, }; AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdLogin, ProtoBufHelper.Serizlize(msg)); } @@ -26,13 +34,13 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Manager if (msg.Status == LoginResultStatus.Ok) { AppNoSugarNet.log.Info("登录成功"); - AppNoSugarNet.user.InitMainUserData(AppNoSugarNet.user.userdata.Account); + AppNoSugarNet.user.InitMainUserData(AppNoSugarNet.user.userdata.Account,msg.UID); + AppNoSugarNet.reverselocal.Send_ClientCfg(); } else { AppNoSugarNet.log.Info("登录失败"); } } - } } diff --git a/NoSugarNet.ClientCore.Standard2/Manager/AppReverseLocalClient.cs b/NoSugarNet.ClientCore.Standard2/Manager/AppReverseLocalClient.cs new file mode 100644 index 0000000..663f59b --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/Manager/AppReverseLocalClient.cs @@ -0,0 +1,365 @@ +using AxibugProtobuf; +using Google.Protobuf; +using NoSugarNet.Adapter; +using NoSugarNet.Adapter.DataHelper; +using NoSugarNet.ClientCore; +using NoSugarNet.ClientCore.Common; +using NoSugarNet.ClientCore.Network; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace ServerCore.Manager +{ + public class AppReverseLocalClient + { + Dictionary mDictCommKey2LocalClients = new Dictionary(); + NoSugarNet.Adapter.DataHelper.CompressAdapter mCompressAdapter; + //public LocalMsgQueuePool _localMsgPool = new LocalMsgQueuePool(1000); + + public long tReciveAllLenght { get; private set; } + public long tSendAllLenght { get; private set; } + + Protobuf_Cfgs _Send_Protobuf_Cfgs = new Protobuf_Cfgs(); + + static long GetCommKey(long Uid, int Tunnel, int Idx) + { + return (Uid * 10000000) + (Tunnel * 10000) + Idx; + } + + static long GetUidForCommKey(long CommKey) + { + return CommKey / 10000000; + } + + public AppReverseLocalClient(NoSugarNet.Adapter.DataHelper.E_CompressAdapter compressAdapterType) + { + AppNoSugarNet.log.Debug("Reverse->初始化压缩适配器" + compressAdapterType); + //初始化压缩适配器,暂时使用0,代表压缩类型 + mCompressAdapter = new CompressAdapter(compressAdapterType); + + //注册网络消息 + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CReverseConnect, Recive_TunnelS2CConnect); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CReverseDisconnect, Recive_TunnelS2CDisconnect); + NetMsg.Instance.RegNetMsgEvent((int)CommandID.CmdTunnelS2CReverseData, Recive_TunnelS2CData); + } + + public void GetCurrLenght(out long resultReciveAllLenght, out long resultSendAllLenght) + { + resultReciveAllLenght = 0; + resultSendAllLenght = 0; + long[] Keys = mDictCommKey2LocalClients.Keys.ToArray(); + for (int i = 0; i < Keys.Length; i++) + { + //local和转发 收发相反 + resultSendAllLenght += mDictCommKey2LocalClients[Keys[i]].mReciveAllLenght; + resultReciveAllLenght += mDictCommKey2LocalClients[Keys[i]].mSendAllLenght; + } + } + + public void Send_ClientCfg() + { + AppNoSugarNet.log.Debug("Reverse->-->Send_ClientCfg"); + + _Send_Protobuf_Cfgs.CompressAdapterType = (int)Config.compressAdapterType; + _Send_Protobuf_Cfgs.Cfgs.Clear(); + foreach (var cfg in Config.cfgs) + { + _Send_Protobuf_Cfgs.Cfgs.Add(new Protobuf_Cfgs_Single() { Port = cfg.Value.RemoteLocalPort, TunnelID = cfg.Value.TunnelId }); + } + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdClientCfgs, ProtoBufHelper.Serizlize(_Send_Protobuf_Cfgs)); + } + + + #region 解析服务端下行数据 + public void Recive_TunnelS2CConnect(byte[] reqData) + { + AppNoSugarNet.log.Debug("Reverse->Recive_TunnelS2CConnect"); + Protobuf_Tunnel_Connect msg = ProtoBufHelper.DeSerizlize(reqData); + if (msg.Connected == 1) + OnRemoteLocalConnect((byte)msg.TunnelID, (byte)msg.Idx); + else + OnRemoteLocalDisconnect((byte)msg.TunnelID, (byte)msg.Idx); + } + public void Recive_TunnelS2CDisconnect(byte[] reqData) + { + AppNoSugarNet.log.Debug("Reverse->Recive_TunnelS2CDisconnect"); + Protobuf_Tunnel_Disconnect msg = ProtoBufHelper.DeSerizlize(reqData); + OnRemoteLocalDisconnect((byte)msg.TunnelID, (byte)msg.Idx); + } + public void Recive_TunnelS2CData(byte[] reqData) + { + Protobuf_Tunnel_DATA msg = ProtoBufHelper.DeSerizlize(reqData); + OnRemoteTunnelDataCallBack(AppNoSugarNet.user.userdata.UID, (byte)msg.TunnelID, (byte)msg.Idx, msg.HunterNetCoreData.ToArray()); + } + #endregion + + + #region 两端本地端口连接事件通知 + + /// + /// 当服务端本地端口连接 + /// + /// + public void OnRemoteLocalConnect(byte tunnelId, byte Idx) + { + AppNoSugarNet.log.Debug($"Reverse->OnRemoteLocalConnect{AppNoSugarNet.user.userdata.UID},{tunnelId},{Idx}"); + + if (!Config.cfgs.ContainsKey(tunnelId)) + return; + + //开一个线程去建立连接 + Thread thread = new Thread(() => + { + //服务器本地局域网连接指定端口 + TunnelClientData tunnelDataCfg = Config.cfgs[tunnelId]; + BackwardLocalClient serverLocalClient = new BackwardLocalClient(AppNoSugarNet.user.userdata.UID, tunnelId, (byte)Idx); + serverLocalClient.BandEvent(AppNoSugarNet.log.Log, OnClientLocalConnect, OnClientLocalDisconnect, OnClientLocalDataCallBack); + //连接成功 + if (!serverLocalClient.Init(tunnelDataCfg.LocalTargetIP, tunnelDataCfg.LocalTargetPort)) + { + //TODO告知客户端连接失败 + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_Connect() + { + TunnelID = tunnelId, + Idx = (uint)Idx, + Connected = 0//失败 + }); + //发送给客户端,指定服务端本地端口已连接 + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SReverseConnect, respData); + } + }); + thread.Start(); + } + /// + /// 当服务端本地端口连接断开 + /// + /// + /// + public void OnRemoteLocalDisconnect(byte tunnelId, byte Idx) + { + AppNoSugarNet.log.Debug($"Reverse->OnRemoteLocalDisconnect {AppNoSugarNet.user.userdata.UID},{tunnelId},{Idx}"); + + //隧道ID定位投递服务端本地连接 + if (!GetClientLocalClient(AppNoSugarNet.user.userdata.UID, tunnelId, Idx, out BackwardLocalClient LocalClient)) + return; + + //断开服务端本地客户端连接 + CloseClientLocalClient(AppNoSugarNet.user.userdata.UID, tunnelId, Idx); + } + + /// + /// 当服务端本地端口连接 + /// + /// + /// + public void OnClientLocalConnect(long uid, byte tunnelId, byte Idx, BackwardLocalClient serverLocalClient) + { + AppNoSugarNet.log.Debug($"Reverse->OnServerLocalConnect {uid},{tunnelId},{Idx}"); + + //添加到服务端本地连接列表 + AddClientLocalClient(uid, tunnelId, Idx, serverLocalClient); + + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_Connect() + { + TunnelID = tunnelId, + Idx = Idx, + Connected = 1 + }); + //发送给客户端,指定服务端本地端口已连接 + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SReverseConnect, respData); + } + /// + /// 当服务端本地端口连接断开 + /// + /// + /// + public void OnClientLocalDisconnect(long uid, byte tunnelId, byte Idx, BackwardLocalClient serverLocalClient) + { + AppNoSugarNet.log.Debug($"Reverse->OnClientLocalDisconnect {uid},{tunnelId},{Idx}"); + //移除到服务端本地连接列表 + RemoveClientLocalClient(uid, tunnelId, Idx); + + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_Disconnect() + { + TunnelID = tunnelId, + Idx = Idx, + }); + //发送给客户端,指定服务端本地端口连接已断开 + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SReverseDisconnect, respData); + } + #endregion + + #region 连接字典管理 + /// + /// 追加连接 + /// + /// + /// + /// + void AddClientLocalClient(long uid, byte tunnelId, byte Idx, BackwardLocalClient serverClient) + { + long CommKey = GetCommKey(uid, tunnelId, Idx); + lock (mDictCommKey2LocalClients) + { + mDictCommKey2LocalClients[CommKey] = serverClient; + } + } + /// + /// 删除连接 + /// + /// + /// + void RemoveClientLocalClient(long uid, byte tunnelId, byte Idx) + { + lock (mDictCommKey2LocalClients) + { + long CommKey = GetCommKey(uid, tunnelId, Idx); + + if (!mDictCommKey2LocalClients.ContainsKey(CommKey)) + return; + mDictCommKey2LocalClients[CommKey].Release(); + mDictCommKey2LocalClients.Remove(CommKey); + } + } + + bool GetClientLocalClient(long uid, byte tunnelId, byte Idx, out BackwardLocalClient serverLocalClient) + { + serverLocalClient = null; + + long CommKey = GetCommKey(uid, tunnelId, Idx); + + if (!mDictCommKey2LocalClients.ContainsKey(CommKey)) + return false; + + serverLocalClient = mDictCommKey2LocalClients[CommKey]; + return true; + } + + void CloseClientLocalClient(long uid, byte tunnelId, byte Idx) + { + //隧道ID定位投递服务端本地连接 + if (!GetClientLocalClient(uid, tunnelId, Idx, out BackwardLocalClient _LocalClient)) + return; + _LocalClient.CloseConntect(); + RemoveClientLocalClient(uid, tunnelId, Idx); + } + + public void GetClientCount(out int ClientUserCount, out int TunnelCount) + { + TunnelCount = mDictCommKey2LocalClients.Count; + long[] CommIDKeys = mDictCommKey2LocalClients.Keys.ToArray(); + List TempHadLocalConnetList = new List(); + for (int i = 0; i < CommIDKeys.Length; i++) + { + long uid = GetUidForCommKey(CommIDKeys[i]); + if (!TempHadLocalConnetList.Contains(uid)) + TempHadLocalConnetList.Add(uid); + } + ClientUserCount = TempHadLocalConnetList.Count; + } + + public void StopAll(long Uid) + { + List TempRemoveCommIDList = new List(); + lock (mDictCommKey2LocalClients) + { + long[] CommIDKeys = mDictCommKey2LocalClients.Keys.ToArray(); + for (int i = 0; i < CommIDKeys.Length; i++) + { + long CommID = CommIDKeys[i]; + long tempUid = GetUidForCommKey(CommID); + if (tempUid == Uid) + TempRemoveCommIDList.Add(CommID); + } + } + + for (int i = 0; i < TempRemoveCommIDList.Count; i++) + { + long CommID = TempRemoveCommIDList[i]; + if (!mDictCommKey2LocalClients.ContainsKey(CommID)) + continue; + BackwardLocalClient _serverLoackClient = mDictCommKey2LocalClients[CommID]; + _serverLoackClient.CloseConntect(); + } + } + #endregion + + + #region 数据投递 + /// + /// 来自客户端本地连接投递的Tunnel数据 + /// + /// + /// + /// + public void OnRemoteTunnelDataCallBack(long uid, byte tunnelId, byte Idx, byte[] data) + { + //隧道ID定位投递服务端本地连接 + if (!GetClientLocalClient(uid, tunnelId, Idx, out BackwardLocalClient serverLocalClient)) + return; + //记录数据长度 + tReciveAllLenght += data.Length; + //解压 + data = mCompressAdapter.Decompress(data); + //记录数据长度 + serverLocalClient.mSendAllLenght += data.LongLength; + //发送给对应服务端本地连接数据 + serverLocalClient.SendToServer(data); + } + /// + /// 来自服务端本地连接投递的Tunnel数据 + /// + /// + /// + /// + public void OnClientLocalDataCallBack(long uid, byte tunnelId, byte Idx, byte[] data) + { + //AppNoSugarNet.log.Debug($"Reverse->OnClientLocalDataCallBack {uid},{tunnelId},{Idx},data -> {data.Length}"); + int SlienLenght = 1000; + //判断数据量大时分包 + if (data.Length > SlienLenght) + { + Span tempSpan = data; + Span tempSpanSlien = null; + int PageCount = (int)(data.Length / SlienLenght); + if (data.Length % SlienLenght > 0) + { + PageCount++; + } + + for (int i = 0; i < PageCount; i++) + { + int StartIdx = i * SlienLenght; + if (i != PageCount - 1)//不是最后一个包 + tempSpanSlien = tempSpan.Slice(StartIdx, SlienLenght); + else//最后一个 + tempSpanSlien = tempSpan.Slice(StartIdx); + + SendDataToRemote(uid, tunnelId, Idx, tempSpanSlien.ToArray()); + } + return; + } + SendDataToRemote(uid, tunnelId, Idx, data); + } + void SendDataToRemote(long uid, byte tunnelId, byte Idx, byte[] data) + { + //压缩 + data = mCompressAdapter.Compress(data); + //记录压缩后数据长度 + tSendAllLenght += data.Length; + + byte[] respData = ProtoBufHelper.Serizlize(new Protobuf_Tunnel_DATA() + { + TunnelID = tunnelId, + Idx = Idx, + HunterNetCoreData = ByteString.CopyFrom(data) + }); + + //发送给客户端,指定客户端本地隧道ID + AppNoSugarNet.networkHelper.SendToServer((int)CommandID.CmdTunnelC2SReverseData, respData); + } + #endregion + } +} \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener.cs b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener.cs index 641023b..a4cc697 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener.cs @@ -1,264 +1,295 @@ -using HaoYueNet.ServerNetwork.Standard2; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Sockets; +//using HaoYueNet.ServerNetwork; +//using System.Net.Sockets; -namespace NoSugarNet.ClientCoreNet.Standard2 -{ - public class LocalListener : TcpSaeaServer_SourceMode - { - public byte mTunnelID; - public long mReciveAllLenght; - public long mSendAllLenght; - public LocalListener(int numConnections, int receiveBufferSize, byte TunnelID) - : base(numConnections, receiveBufferSize) - { - OnClientNumberChange += ClientNumberChange; - OnReceive += ReceiveData; - OnDisconnected += OnDisconnect; - OnNetLog += OnShowNetLog; +//namespace NoSugarNet.ClientCore +//{ +// public class LocalListener : TcpSaeaServer_SourceMode +// { +// public byte mTunnelID; +// public long mReciveAllLenght; +// public long mSendAllLenght; +// public long currSeed; +// static long Seed; - mTunnelID = TunnelID; - } +// public LocalListener(int numConnections, int receiveBufferSize, byte TunnelID) +// : base(numConnections, receiveBufferSize) +// { +// OnClientNumberChange += ClientNumberChange; +// OnReceive += ReceiveData; +// OnDisconnected += OnDisconnect; +// OnNetLog += OnShowNetLog; - private void ClientNumberChange(int num, AsyncUserToken token) - { - AppNoSugarNet.log.Info("Client数发生变化"); - //增加连接数 - if (num > 0) - { - int Idx = AddDictSocket(token.Socket); - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) - { - AppNoSugarNet.local.OnClientLocalConnect(mTunnelID, (byte)Idx); - } - } - } +// mTunnelID = TunnelID; - /// - /// 通过下标发送 - /// - /// - /// - public void SendSocketByIdx(int Idx, byte[] data) - { - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - { - mSendAllLenght += data.Length; - SendToSocket(_localClientInfo._socket, data); - } - //TODO连接前缓存数据 - } +// currSeed = Seed++; +// } - /// - /// 接受包回调 - /// - /// 协议ID - /// 错误编号 - /// 业务数据 - private void ReceiveData(AsyncUserToken token, byte[] data) - { - DataCallBack(token.Socket, data); - } +// private void ClientNumberChange(int num, AsyncUserToken token) +// { +// AppNoSugarNet.log.Info("Client数发生变化"); +// //增加连接数stsc +// if (num > 0) +// { +// int Idx = AddDictSocket(token.Socket); +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) +// { +// AppNoSugarNet.local.OnClientLocalConnect(mTunnelID, (byte)Idx); +// } +// } +// } - public void DataCallBack(Socket sk, byte[] data) - { - //AppNoSugarNet.log.Info("收到消息 数据长度=>" + data.Length); - //记录接受长度 - mReciveAllLenght += data.Length; - if (!GetSocketIdxBySocket(sk, out int Idx)) - return; - try - { - //抛出网络数据 - AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, data); - } - catch (Exception ex) - { - AppNoSugarNet.log.Info("逻辑处理错误:" + ex.ToString()); - } - } +// /// +// /// 通过下标发送 +// /// +// /// +// /// +// public void SendSocketByIdx(int Idx, byte[] data) +// { +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// { +// mSendAllLenght += data.Length; +// SendToSocket(_localClientInfo._socket, data); +// } +// //TODO连接前缓存数据 +// } - public void CloseConnectByIdx(byte Idx) - { - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) - { - _localClientInf._socket.Shutdown(SocketShutdown.Both); - } - } +// /// +// /// 接受包回调 +// /// +// /// 协议ID +// /// 错误编号 +// /// 业务数据 +// private void ReceiveData(AsyncUserToken token, byte[] data) +// { +// DataCallBack(token.Socket, data); +// } - /// - /// 断开连接 - /// - /// - public void OnDisconnect(AsyncUserToken token) - { - AppNoSugarNet.log.Info("断开连接"); +// public void DataCallBack(Socket sk, byte[] data) +// { +// //AppNoSugarNet.log.Info("收到消息 数据长度=>" + data.Length); +// //记录接受长度 +// mReciveAllLenght += data.Length; +// if (!GetSocketIdxBySocket(sk, out int Idx)) +// return; +// try +// { +// //抛出网络数据 +// AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, data); +// } +// catch (Exception ex) +// { +// AppNoSugarNet.log.Info("逻辑处理错误:" + ex.ToString()); +// } +// } - if (!GetSocketIdxBySocket(token.Socket, out int Idx)) - return; +// public void CloseConnectByIdx(byte Idx) +// { +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// { +// //把未发送消息队列回收了 +// while (_localClientInfo.msgQueue.Count > 0) +// { +// IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); +// AppNoSugarNet.local._localMsgPool.Enqueue(msg); +// } - AppNoSugarNet.local.OnClientLocalDisconnect(mTunnelID, (byte)Idx); - RemoveDictSocket(token.Socket); - } +// _localClientInfo._socket.Shutdown(SocketShutdown.Both); +// } +// } - public void OnShowNetLog(string msg) - { - AppNoSugarNet.log.Info(msg); - } +// /// +// /// 断开连接 +// /// +// /// +// public void OnDisconnect(AsyncUserToken token) +// { +// AppNoSugarNet.log.Info("断开连接"); - #region 一个轻量级无用户连接管理 - Dictionary DictSocketHandle2Idx = new Dictionary(); - Dictionary DictIdx2LocalClientInfo = new Dictionary(); - int mSeedIdx = 0; - List FreeIdxs = new List(); - public class LocalClientInfo - { - public Socket _socket; - public bool bRemoteConnect; - public bool bLocalConnect => _socket.Connected; - public Queue msgQueue = new Queue(); - } +// if (!GetSocketIdxBySocket(token.Socket, out int Idx)) +// return; - int GetNextIdx() - { - if (FreeIdxs.Count > 0) - { - int Idx = FreeIdxs[0]; - FreeIdxs.RemoveAt(0); - return Idx; - } - return mSeedIdx++; - } +// AppNoSugarNet.local.OnClientLocalDisconnect(mTunnelID, (byte)Idx); +// RemoveDictSocket(token.Socket); +// } - /// - /// 追加Socket返回下标 - /// - /// - /// - public int AddDictSocket(Socket socket) - { - if (socket == null) - return -1; - lock (DictSocketHandle2Idx) - { - int Idx = GetNextIdx(); - DictSocketHandle2Idx[socket.Handle] = Idx; - DictIdx2LocalClientInfo[Idx] = new LocalClientInfo() { _socket = socket,bRemoteConnect = false}; - return Idx; - } - } +// public void OnShowNetLog(string msg) +// { +// AppNoSugarNet.log.Info(msg); +// } - public void RemoveDictSocket(Socket socket) - { - if (socket == null) - return; - lock (DictSocketHandle2Idx) - { - if (!DictSocketHandle2Idx.ContainsKey(socket.Handle)) - return; - int Idx = DictSocketHandle2Idx[socket.Handle]; - FreeIdxs.Add(Idx); - if (DictIdx2LocalClientInfo.ContainsKey(Idx)) - DictIdx2LocalClientInfo.Remove(Idx); - DictSocketHandle2Idx.Remove(socket.Handle); - } - } +// #region 一个轻量级无用户连接管理 +// Dictionary DictSocketHandle2Idx = new Dictionary(); +// Dictionary DictIdx2LocalClientInfo = new Dictionary(); +// int mSeedIdx = 0; +// List FreeIdxs = new List(); +// public class LocalClientInfo +// { +// public Socket _socket; +// public bool bRemoteConnect; +// public bool bLocalConnect => _socket.Connected; +// public Queue msgQueue = new Queue(); +// } - bool GetSocketByIdx(int Idx, out LocalClientInfo _localClientInfo) - { - if (!DictIdx2LocalClientInfo.ContainsKey(Idx)) - { - _localClientInfo = null; - return false; - } +// public Dictionary GetDictIdx2LocalClientInfo() +// { +// return DictIdx2LocalClientInfo; +// } - _localClientInfo = DictIdx2LocalClientInfo[Idx]; - return true; - } +// int GetNextIdx() +// { +// if (FreeIdxs.Count > 0) +// { +// int Idx = FreeIdxs[0]; +// FreeIdxs.RemoveAt(0); +// return Idx; +// } +// return mSeedIdx++; +// } - public bool GetSocketIdxBySocket(Socket _socket, out int Idx) - { - if (_socket == null) - { - Idx = -1; - return false; - } +// void ResetFree() +// { +// FreeIdxs.Clear(); +// mSeedIdx = 0; +// } - if (!DictSocketHandle2Idx.ContainsKey(_socket.Handle)) - { - Idx = -1; - return false; - } +// /// +// /// 追加Socket返回下标 +// /// +// /// +// /// +// public int AddDictSocket(Socket socket) +// { +// if (socket == null) +// return -1; +// lock (DictSocketHandle2Idx) +// { +// int Idx = GetNextIdx(); +// DictSocketHandle2Idx[socket.Handle] = Idx; +// DictIdx2LocalClientInfo[Idx] = new LocalClientInfo() { _socket = socket,bRemoteConnect = false}; +// AppNoSugarNet.log.Debug($"AddDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); +// return Idx; +// } +// } - Idx = DictSocketHandle2Idx[_socket.Handle]; - return true; - } +// public void RemoveDictSocket(Socket socket) +// { +// if (socket == null) +// return; +// lock (DictSocketHandle2Idx) +// { +// if (!DictSocketHandle2Idx.ContainsKey(socket.Handle)) +// return; +// int Idx = DictSocketHandle2Idx[socket.Handle]; +// FreeIdxs.Add(Idx); +// if (DictIdx2LocalClientInfo.ContainsKey(Idx)) +// DictIdx2LocalClientInfo.Remove(Idx); +// DictSocketHandle2Idx.Remove(socket.Handle); +// AppNoSugarNet.log.Debug($"RemoveDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); +// } +// } - public bool CheckRemoteConnect(int Idx) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return false; - return _localClientInfo.bRemoteConnect; - } +// bool GetSocketByIdx(int Idx, out LocalClientInfo _localClientInfo) +// { +// if (!DictIdx2LocalClientInfo.ContainsKey(Idx)) +// { +// _localClientInfo = null; +// return false; +// } - public void SetRemoteConnectd(int Idx,bool bConnected) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return; - if (bConnected) - AppNoSugarNet.log.Info("远端本地连接已连接!!!!"); - else - AppNoSugarNet.log.Info("远端本地连接已断开连接!!!!"); - _localClientInfo.bRemoteConnect = bConnected; - } +// _localClientInfo = DictIdx2LocalClientInfo[Idx]; +// return true; +// } - public void StopAll() - { - lock (DictIdx2LocalClientInfo) - { - int[] Idxs = DictIdx2LocalClientInfo.Keys.ToArray(); - for (int i = 0; i < Idxs.Length; i++) - { - CloseConnectByIdx((byte)Idxs[i]); - } - DictIdx2LocalClientInfo.Clear(); - } - } +// public bool GetSocketIdxBySocket(Socket _socket, out int Idx) +// { +// if (_socket == null) +// { +// Idx = -1; +// return false; +// } - #endregion +// if (!DictSocketHandle2Idx.ContainsKey(_socket.Handle)) +// { +// Idx = -1; +// return false; +// } - #region 缓存 - public void EnqueueIdxWithMsg(byte Idx, byte[] data) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return; +// Idx = DictSocketHandle2Idx[_socket.Handle]; +// return true; +// } - IdxWithMsg Msg = AppNoSugarNet.local._localMsgPool.Dequeue(); - Msg.Idx = Idx; - Msg.data = data; - _localClientInfo.msgQueue.Enqueue(Msg); - } - public bool GetDictMsgQueue(byte Idx,out List MsgList) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo) || _localClientInfo.msgQueue.Count < 1) - { - MsgList = null; - return false; - } +// public bool CheckRemoteConnect(int Idx) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return false; +// return _localClientInfo.bRemoteConnect; +// } - MsgList = new List(); - lock (_localClientInfo.msgQueue) - { - while (_localClientInfo.msgQueue.Count > 0) - { - IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); - MsgList.Add(msg); - } - return true; - } - } - #endregion - } -} +// public void SetRemoteConnectd(int Idx,bool bConnected) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return; +// if (bConnected) +// AppNoSugarNet.log.Info("远端本地连接已连接!!!!"); +// else +// AppNoSugarNet.log.Info("远端本地连接已断开连接!!!!"); +// _localClientInfo.bRemoteConnect = bConnected; +// } + +// public void StopAllLocalClient() +// { +// lock (DictIdx2LocalClientInfo) +// { +// int[] Idxs = DictIdx2LocalClientInfo.Keys.ToArray(); +// for (int i = 0; i < Idxs.Length; i++) +// { +// CloseConnectByIdx((byte)Idxs[i]); +// } +// DictIdx2LocalClientInfo.Clear(); +// DictSocketHandle2Idx.Clear(); +// ResetFree(); + +// //清理事件 +// OnClientNumberChange -= ClientNumberChange; +// OnReceive -= ReceiveData; +// OnDisconnected -= OnDisconnect; +// OnNetLog -= OnShowNetLog; +// } +// } + +// #endregion + + +// #region 缓存 +// public void EnqueueIdxWithMsg(byte Idx, byte[] data) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return; + +// IdxWithMsg Msg = AppNoSugarNet.local._localMsgPool.Dequeue(); +// Msg.Idx = Idx; +// Msg.data = data; +// _localClientInfo.msgQueue.Enqueue(Msg); +// } +// public bool GetDictMsgQueue(byte Idx,out List MsgList) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo) || _localClientInfo.msgQueue.Count < 1) +// { +// MsgList = null; +// return false; +// } + +// MsgList = new List(); +// lock (_localClientInfo.msgQueue) +// { +// while (_localClientInfo.msgQueue.Count > 0) +// { +// IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); +// MsgList.Add(msg); +// } +// return true; +// } +// } +// #endregion +// } +//} diff --git a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener_Source.cs b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener_Source.cs index 57f3da7..69e9a15 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener_Source.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalListener_Source.cs @@ -1,292 +1,296 @@ -using HaoYueNet.ClientNetworkNet.Standard2.OtherMode; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Sockets; +//using HaoYueNet.ClientNetwork.OtherMode; +//using HaoYueNet.ServerNetwork; +//using System.Net.Sockets; -namespace NoSugarNet.ClientCoreNet.Standard2 -{ - public class LocalListener_Source : NetworkHelperCore_ListenerMode - { - public byte mTunnelID; - public long mReciveAllLenght; - public long mSendAllLenght; - public LocalListener_Source(int numConnections, int receiveBufferSize, byte TunnelID) - : base() - { - OnConnected += ClientNumberChange; - OnReceive += ReceiveData; - OnDisconnected += OnDisconnectClient; - OnNetLog += OnShowNetLog; +//namespace NoSugarNet.ClientCore +//{ +// public class LocalListener_Source : NetworkHelperCore_ListenerMode +// { +// public byte mTunnelID; +// public long mReciveAllLenght; +// public long mSendAllLenght; +// public LocalListener_Source(int numConnections, int receiveBufferSize, byte TunnelID) +// : base() +// { +// OnConnected += ClientNumberChange; +// OnReceive += ReceiveData; +// OnDisconnected += OnDisconnectClient; +// OnNetLog += OnShowNetLog; - mTunnelID = TunnelID; - } +// mTunnelID = TunnelID; +// } - private void ClientNumberChange(Socket socket) - { - AppNoSugarNet.log.Info("Client数发生变化"); - //增加连接数 - int Idx = AddDictSocket(socket); - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) - { - AppNoSugarNet.local.OnClientLocalConnect(mTunnelID, (byte)Idx); - } - } +// private void ClientNumberChange(Socket socket) +// { +// AppNoSugarNet.log.Info("Client数发生变化"); +// //增加连接数 +// int Idx = AddDictSocket(socket); +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) +// { +// AppNoSugarNet.local.OnClientLocalConnect(mTunnelID, (byte)Idx); +// } +// } - /// - /// 通过下标发送 - /// - /// - /// - public void SendSocketByIdx(int Idx, byte[] data) - { - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - { - mSendAllLenght += data.Length; - SendToClient(_localClientInfo._socket, data); - } - //TODO连接前缓存数据 - } +// /// +// /// 通过下标发送 +// /// +// /// +// /// +// public void SendSocketByIdx(int Idx, byte[] data) +// { +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// { +// mSendAllLenght += data.Length; +// SendToClient(_localClientInfo._socket, data); +// } +// //TODO连接前缓存数据 +// } - /// - /// 接受包回调 - /// - /// 协议ID - /// 错误编号 - /// 业务数据 - private void ReceiveData(Socket sk, byte[] data) - { - DataCallBack(sk, data); - } +// /// +// /// 接受包回调 +// /// +// /// 协议ID +// /// 错误编号 +// /// 业务数据 +// private void ReceiveData(Socket sk, byte[] data) +// { +// DataCallBack(sk, data); +// } - public void DataCallBack(Socket sk, byte[] data) - { - //AppNoSugarNet.log.Info("收到消息 数据长度=>" + data.Length); - //记录接受长度 - mReciveAllLenght += data.Length; - if (!GetSocketIdxBySocket(sk, out int Idx)) - return; - try - { - if (GetMsgQueueByIdx(sk.Handle, out Queue _queue)) - { - lock (_queue) - { - _queue.Enqueue(data); - while (_queue.Count > 0) - { - AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, _queue.Dequeue()); - } - } - } +// public void DataCallBack(Socket sk, byte[] data) +// { +// //AppNoSugarNet.log.Info("收到消息 数据长度=>" + data.Length); +// //记录接受长度 +// mReciveAllLenght += data.Length; +// if (!GetSocketIdxBySocket(sk, out int Idx)) +// return; +// try +// { +// if (GetMsgQueueByIdx(sk.Handle, out Queue _queue)) +// { +// lock (_queue) +// { +// _queue.Enqueue(data); +// while (_queue.Count > 0) +// { +// AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, _queue.Dequeue()); +// } +// } +// } - ////抛出网络数据 - //AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, data); - } - catch (Exception ex) - { - AppNoSugarNet.log.Info("逻辑处理错误:" + ex.ToString()); - } - } +// ////抛出网络数据 +// //AppNoSugarNet.local.OnClientTunnelDataCallBack(mTunnelID, (byte)Idx, data); +// } +// catch (Exception ex) +// { +// AppNoSugarNet.log.Info("逻辑处理错误:" + ex.ToString()); +// } +// } - public void CloseConnectByIdx(byte Idx) - { - if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) - { - _localClientInf._socket.Shutdown(SocketShutdown.Both); - } - } +// public void CloseConnectByIdx(byte Idx) +// { +// if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) +// { +// _localClientInf._socket.Shutdown(SocketShutdown.Both); +// } +// } - /// - /// 断开连接 - /// - /// - public void OnDisconnectClient(Socket sk) - { - AppNoSugarNet.log.Info("断开连接"); +// /// +// /// 断开连接 +// /// +// /// +// public void OnDisconnectClient(Socket sk) +// { +// AppNoSugarNet.log.Info("断开连接"); - if (!GetSocketIdxBySocket(sk, out int Idx)) - return; +// if (!GetSocketIdxBySocket(sk, out int Idx)) +// return; - AppNoSugarNet.local.OnClientLocalDisconnect(mTunnelID, (byte)Idx); - RemoveDictSocket(sk); - } +// AppNoSugarNet.local.OnClientLocalDisconnect(mTunnelID, (byte)Idx); +// RemoveDictSocket(sk); +// } - public void OnShowNetLog(string msg) - { - AppNoSugarNet.log.Info(msg); - } +// public void OnShowNetLog(string msg) +// { +// AppNoSugarNet.log.Info(msg); +// } - #region 一个轻量级无用户连接管理 - Dictionary DictSocketHandle2Idx = new Dictionary(); - Dictionary> DictSocketHandle2Msg = new Dictionary>(); - Dictionary DictIdx2LocalClientInfo = new Dictionary(); - int mSeedIdx = 0; - List FreeIdxs = new List(); - public class LocalClientInfo - { - public Socket _socket; - public bool bRemoteConnect; - public bool bLocalConnect => _socket.Connected; - public Queue msgQueue = new Queue(); - } +// #region 一个轻量级无用户连接管理 +// Dictionary DictSocketHandle2Idx = new Dictionary(); +// Dictionary> DictSocketHandle2Msg = new Dictionary>(); +// Dictionary DictIdx2LocalClientInfo = new Dictionary(); +// int mSeedIdx = 0; +// List FreeIdxs = new List(); +// public class LocalClientInfo +// { +// public Socket _socket; +// public bool bRemoteConnect; +// public bool bLocalConnect => _socket.Connected; +// public Queue msgQueue = new Queue(); +// } - int GetNextIdx() - { - if (FreeIdxs.Count > 0) - { - int Idx = FreeIdxs[0]; - FreeIdxs.RemoveAt(0); - return Idx; - } - return mSeedIdx++; - } +// int GetNextIdx() +// { +// if (FreeIdxs.Count > 0) +// { +// int Idx = FreeIdxs[0]; +// FreeIdxs.RemoveAt(0); +// return Idx; +// } +// return mSeedIdx++; +// } - /// - /// 追加Socket返回下标 - /// - /// - /// - public int AddDictSocket(Socket socket) - { - if (socket == null) - return -1; - lock (DictSocketHandle2Idx) - { - int Idx = GetNextIdx(); - DictSocketHandle2Idx[socket.Handle] = Idx; - DictIdx2LocalClientInfo[Idx] = new LocalClientInfo() { _socket = socket,bRemoteConnect = false}; - DictSocketHandle2Msg[socket.Handle] = new Queue(); - return Idx; - } - } +// /// +// /// 追加Socket返回下标 +// /// +// /// +// /// +// public int AddDictSocket(Socket socket) +// { +// if (socket == null) +// return -1; - public void RemoveDictSocket(Socket socket) - { - if (socket == null) - return; - lock (DictSocketHandle2Idx) - { - if (!DictSocketHandle2Idx.ContainsKey(socket.Handle)) - return; - int Idx = DictSocketHandle2Idx[socket.Handle]; - FreeIdxs.Add(Idx); - if (DictIdx2LocalClientInfo.ContainsKey(Idx)) - DictIdx2LocalClientInfo.Remove(Idx); +// lock (DictSocketHandle2Idx) +// { +// int Idx = GetNextIdx(); +// DictSocketHandle2Idx[socket.Handle] = Idx; +// DictIdx2LocalClientInfo[Idx] = new LocalClientInfo() { _socket = socket,bRemoteConnect = false}; +// DictSocketHandle2Msg[socket.Handle] = new Queue(); +// AppNoSugarNet.log.Debug($"AddDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); +// return Idx; +// } +// } + +// public void RemoveDictSocket(Socket socket) +// { +// if (socket == null) +// return; +// lock (DictSocketHandle2Idx) +// { +// if (!DictSocketHandle2Idx.ContainsKey(socket.Handle)) +// return; +// int Idx = DictSocketHandle2Idx[socket.Handle]; +// FreeIdxs.Add(Idx); +// if (DictIdx2LocalClientInfo.ContainsKey(Idx)) +// DictIdx2LocalClientInfo.Remove(Idx); - if (DictSocketHandle2Msg.ContainsKey(socket.Handle)) - DictSocketHandle2Msg.Remove(socket.Handle); +// if (DictSocketHandle2Msg.ContainsKey(socket.Handle)) +// DictSocketHandle2Msg.Remove(socket.Handle); - DictSocketHandle2Idx.Remove(socket.Handle); - } - } +// DictSocketHandle2Idx.Remove(socket.Handle); - bool GetSocketByIdx(int Idx, out LocalClientInfo _localClientInfo) - { - if (!DictIdx2LocalClientInfo.ContainsKey(Idx)) - { - _localClientInfo = null; - return false; - } +// AppNoSugarNet.log.Debug($"RemoveDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); +// } +// } - _localClientInfo = DictIdx2LocalClientInfo[Idx]; - return true; - } +// bool GetSocketByIdx(int Idx, out LocalClientInfo _localClientInfo) +// { +// if (!DictIdx2LocalClientInfo.ContainsKey(Idx)) +// { +// _localClientInfo = null; +// return false; +// } - bool GetMsgQueueByIdx(IntPtr handle, out Queue _queue) - { - if (!DictSocketHandle2Msg.ContainsKey(handle)) - { - _queue = null; - return false; - } +// _localClientInfo = DictIdx2LocalClientInfo[Idx]; +// return true; +// } - _queue = DictSocketHandle2Msg[handle]; - return true; - } +// bool GetMsgQueueByIdx(IntPtr handle, out Queue _queue) +// { +// if (!DictSocketHandle2Msg.ContainsKey(handle)) +// { +// _queue = null; +// return false; +// } - public bool GetSocketIdxBySocket(Socket _socket, out int Idx) - { - if (_socket == null) - { - Idx = -1; - return false; - } +// _queue = DictSocketHandle2Msg[handle]; +// return true; +// } - if (!DictSocketHandle2Idx.ContainsKey(_socket.Handle)) - { - Idx = -1; - return false; - } +// public bool GetSocketIdxBySocket(Socket _socket, out int Idx) +// { +// if (_socket == null) +// { +// Idx = -1; +// return false; +// } - Idx = DictSocketHandle2Idx[_socket.Handle]; - return true; - } +// if (!DictSocketHandle2Idx.ContainsKey(_socket.Handle)) +// { +// Idx = -1; +// return false; +// } - public bool CheckRemoteConnect(int Idx) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return false; - return _localClientInfo.bRemoteConnect; - } +// Idx = DictSocketHandle2Idx[_socket.Handle]; +// return true; +// } - public void SetRemoteConnectd(int Idx,bool bConnected) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return; - if (bConnected) - AppNoSugarNet.log.Info("远端本地连接已连接!!!!"); - else - AppNoSugarNet.log.Info("远端本地连接已断开连接!!!!"); - _localClientInfo.bRemoteConnect = bConnected; - } +// public bool CheckRemoteConnect(int Idx) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return false; +// return _localClientInfo.bRemoteConnect; +// } - public void StopAll() - { - lock (DictIdx2LocalClientInfo) - { - int[] Idxs = DictIdx2LocalClientInfo.Keys.ToArray(); - for (int i = 0; i < Idxs.Length; i++) - { - CloseConnectByIdx((byte)Idxs[i]); - } - DictIdx2LocalClientInfo.Clear(); - } - } +// public void SetRemoteConnectd(int Idx,bool bConnected) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return; +// if (bConnected) +// AppNoSugarNet.log.Info("远端本地连接已连接!!!!"); +// else +// AppNoSugarNet.log.Info("远端本地连接已断开连接!!!!"); +// _localClientInfo.bRemoteConnect = bConnected; +// } - #endregion +// public void StopAll() +// { +// lock (DictIdx2LocalClientInfo) +// { +// int[] Idxs = DictIdx2LocalClientInfo.Keys.ToArray(); +// for (int i = 0; i < Idxs.Length; i++) +// { +// CloseConnectByIdx((byte)Idxs[i]); +// } +// DictIdx2LocalClientInfo.Clear(); +// FreeIdxs.Clear(); +// mSeedIdx = 0; +// } +// } + +// #endregion - #region 缓存 - public void EnqueueIdxWithMsg(byte Idx, byte[] data) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) - return; +// #region 缓存 +// public void EnqueueIdxWithMsg(byte Idx, byte[] data) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) +// return; - IdxWithMsg Msg = AppNoSugarNet.local._localMsgPool.Dequeue(); - Msg.Idx = Idx; - Msg.data = data; - _localClientInfo.msgQueue.Enqueue(Msg); - } - public bool GetDictMsgQueue(byte Idx,out List MsgList) - { - if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo) || _localClientInfo.msgQueue.Count < 1) - { - MsgList = null; - return false; - } +// IdxWithMsg Msg = AppNoSugarNet.local._localMsgPool.Dequeue(); +// Msg.Idx = Idx; +// Msg.data = data; +// _localClientInfo.msgQueue.Enqueue(Msg); +// } +// public bool GetDictMsgQueue(byte Idx,out List MsgList) +// { +// if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo) || _localClientInfo.msgQueue.Count < 1) +// { +// MsgList = null; +// return false; +// } - MsgList = new List(); - lock (_localClientInfo.msgQueue) - { - while (_localClientInfo.msgQueue.Count > 0) - { - IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); - MsgList.Add(msg); - } - return true; - } - } - #endregion - } -} +// MsgList = new List(); +// lock (_localClientInfo.msgQueue) +// { +// while (_localClientInfo.msgQueue.Count > 0) +// { +// IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); +// MsgList.Add(msg); +// } +// return true; +// } +// } +// #endregion +// } +//} diff --git a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalMsgQueuePool.cs b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalMsgQueuePool.cs index 9201ee4..2e98933 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalMsgQueuePool.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/LocalClient/LocalMsgQueuePool.cs @@ -1,55 +1,53 @@ -using System.Collections.Generic; +//namespace NoSugarNet.ClientCore +//{ +// public class IdxWithMsg +// { +// public byte Idx; +// public byte[] data; +// } -namespace NoSugarNet.ClientCoreNet.Standard2 -{ - public class IdxWithMsg - { - public byte Idx; - public byte[] data; - } +// public class LocalMsgQueuePool +// { +// Queue msg_pool; - public class LocalMsgQueuePool - { - Queue msg_pool; +// public LocalMsgQueuePool(int capacity) +// { +// msg_pool = new Queue(capacity); +// } - public LocalMsgQueuePool(int capacity) - { - msg_pool = new Queue(capacity); - } +// /// +// /// 向 Queue 的末尾添加一个对象。 +// /// +// /// +// public void Enqueue(IdxWithMsg item) +// { +// lock (msg_pool) +// { +// item.Idx = 0; +// item.data = null; +// msg_pool.Enqueue(item); +// } +// } - /// - /// 向 Queue 的末尾添加一个对象。 - /// - /// - public void Enqueue(IdxWithMsg item) - { - lock (msg_pool) - { - item.Idx = 0; - item.data = null; - msg_pool.Enqueue(item); - } - } +// //移除并返回在 Queue 的开头的对象。 +// public IdxWithMsg Dequeue() +// { +// lock (msg_pool) +// { +// if(msg_pool.Count > 0) +// return msg_pool.Dequeue(); +// return new IdxWithMsg(); +// } +// } - //移除并返回在 Queue 的开头的对象。 - public IdxWithMsg Dequeue() - { - lock (msg_pool) - { - if(msg_pool.Count > 0) - return msg_pool.Dequeue(); - return new IdxWithMsg(); - } - } +// public int Count +// { +// get { return msg_pool.Count; } +// } - public int Count - { - get { return msg_pool.Count; } - } - - public void Clear() - { - msg_pool.Clear(); - } - } -} +// public void Clear() +// { +// msg_pool.Clear(); +// } +// } +//} diff --git a/NoSugarNet.ClientCore.Standard2/Manager/LogManager.cs b/NoSugarNet.ClientCore.Standard2/Manager/LogManager.cs index e309b0a..e356779 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/LogManager.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/LogManager.cs @@ -1,4 +1,4 @@ -namespace NoSugarNet.ClientCoreNet.Standard2.Manager +namespace NoSugarNet.ClientCore.Manager { public class LogManager { @@ -44,5 +44,10 @@ { OnLog?.Invoke((int)logtype, str); } + + public void Log(int logtype, string str) + { + OnLog?.Invoke(logtype, str); + } } } \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/Manager/UserDataManager.cs b/NoSugarNet.ClientCore.Standard2/Manager/UserDataManager.cs index cf95c10..795136c 100644 --- a/NoSugarNet.ClientCore.Standard2/Manager/UserDataManager.cs +++ b/NoSugarNet.ClientCore.Standard2/Manager/UserDataManager.cs @@ -1,6 +1,6 @@ using AxibugProtobuf; -namespace NoSugarNet.ClientCoreNet.Standard2.Manager +namespace NoSugarNet.ClientCore.Manager { public class UserDataBase { @@ -23,10 +23,11 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Manager public MainUserDataBase userdata { get;private set; } = new MainUserDataBase(); public bool IsLoggedIn => userdata.IsLoggedIn; - public void InitMainUserData(string UName) + public void InitMainUserData(string UName,long UID) { userdata.Account = UName; userdata.IsLoggedIn = true; + userdata.UID = UID; //以及其他数据初始化 //... } @@ -49,7 +50,7 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Manager //如果之前已登录,则重新登录 if (userdata.IsLoggedIn) { - AppNoSugarNet.login.Login(userdata.Account); + AppNoSugarNet.login.Login(); } } } diff --git a/NoSugarNet.ClientCore.Standard2/NetStatus.cs b/NoSugarNet.ClientCore.Standard2/NetStatus.cs index 95392de..b764cd9 100644 --- a/NoSugarNet.ClientCore.Standard2/NetStatus.cs +++ b/NoSugarNet.ClientCore.Standard2/NetStatus.cs @@ -1,4 +1,4 @@ -namespace NoSugarNet.ClientCoreNet.Standard2 +namespace NoSugarNet.ClientCore { public struct NetStatus { diff --git a/NoSugarNet.ClientCore.Standard2/Network/NetMsg.cs b/NoSugarNet.ClientCore.Standard2/Network/NetMsg.cs index 101b5a0..b85a4a2 100644 --- a/NoSugarNet.ClientCore.Standard2/Network/NetMsg.cs +++ b/NoSugarNet.ClientCore.Standard2/Network/NetMsg.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace NoSugarNet.ClientCoreNet.Standard2.Network +namespace NoSugarNet.ClientCore.Network { public class NetMsg diff --git a/NoSugarNet.ClientCore.Standard2/Network/NetworkHelper.cs b/NoSugarNet.ClientCore.Standard2/Network/NetworkHelper.cs index 0a1c387..24582c1 100644 --- a/NoSugarNet.ClientCore.Standard2/Network/NetworkHelper.cs +++ b/NoSugarNet.ClientCore.Standard2/Network/NetworkHelper.cs @@ -1,8 +1,14 @@ -using HaoYueNet.ClientNetworkNet.Standard2; +using AxibugProtobuf; +using Google.Protobuf; +using HaoYueNet.ClientNetwork; using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using System.Threading; +using System.Threading.Tasks; -namespace NoSugarNet.ClientCoreNet.Standard2.Network +namespace NoSugarNet.ClientCore.Network { /// /// 继承网络库,以支持网络功能 @@ -28,7 +34,7 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Network /// /// 是否自动重连 /// - public bool bAutoReConnect = false; + public bool bAutoReConnect = true; /// /// 重连尝试时间 /// @@ -39,12 +45,21 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Network NetworkDeBugLog($"NetworkConnected:{IsConnect}"); if (IsConnect) { - AppNoSugarNet.login.Login(Guid.NewGuid().ToString()); + //从未登录过 + if (!AppNoSugarNet.user.IsLoggedIn) + { + //首次登录 + AppNoSugarNet.login.Login(); + } } else { //连接失败 NetworkDeBugLog("连接失败!"); + + //停止所有 + AppNoSugarNet.forwardlocal.StopAll(); + //自动重连开关 if (bAutoReConnect) ReConnect(); @@ -86,7 +101,8 @@ namespace NoSugarNet.ClientCoreNet.Standard2.Network NetworkDeBugLog("OnConnectClose"); //停止所有 - AppNoSugarNet.local.StopAll(); + AppNoSugarNet.forwardlocal.StopAll(); + AppNoSugarNet.reverselocal.StopAll(AppNoSugarNet.user.userdata.UID); //自动重连开关 if (bAutoReConnect) diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/BackwardLocalClient.cs b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/BackwardLocalClient.cs new file mode 100644 index 0000000..b818ea3 --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/BackwardLocalClient.cs @@ -0,0 +1,113 @@ +using HaoYueNet.ClientNetwork.OtherMode; +using System; + +namespace NoSugarNet.Adapter +{ + /// + /// 继承网络库,以支持网络功能 + /// + public class BackwardLocalClient : NetworkHelperCore_SourceMode + { + public long mUID; + public byte mTunnelID; + public byte mIdx; + public long mReciveAllLenght; + public long mSendAllLenght; + + public delegate void OnBackwardLogOutHandler(int LogLevel, string Msg); + public delegate void OnBackwardConnectHandler(long uid, byte tunnelId, byte Idx, BackwardLocalClient serverLocalClient); + public delegate void OnBackwardDisconnectHandler(long uid, byte tunnelId, byte Idx, BackwardLocalClient serverLocalClient); + public delegate void OnBackwardDataCallBackHandler(long uid, byte tunnelId, byte Idx, byte[] data); + + public event OnBackwardLogOutHandler OnBackwardLogOut; + public event OnBackwardConnectHandler OnBackwardConnect; + public event OnBackwardDisconnectHandler OnBackwardDisconnect; + public event OnBackwardDataCallBackHandler OnBackwardDataCallBack; + + public BackwardLocalClient(long UID,byte TunnelID, byte Idx) + { + mUID = UID; + mTunnelID = TunnelID; + mIdx = Idx; + //指定接收服务器数据事件 + OnReceiveData += GetDataCallBack; + //断开连接 + OnClose += OnConnectClose; + OnConnected += NetworkConnected; + //网络库调试信息输出事件,用于打印网络内容 + OnLogOut += NetworkDeBugLog; + } + + public void BandEvent( + OnBackwardLogOutHandler _OnBackwardLogOut, + OnBackwardConnectHandler _OnConnect, + OnBackwardDisconnectHandler _OnDisconnect, + OnBackwardDataCallBackHandler _OnDataCallBack + ) + { + OnBackwardLogOut += _OnBackwardLogOut; + OnBackwardConnect += _OnConnect; + OnBackwardDisconnect += _OnDisconnect; + OnBackwardDataCallBack += _OnDataCallBack; + } + + public void NetworkConnected(bool IsConnect) + { + NetworkDeBugLog($"NetworkConnected:{IsConnect}"); + if (IsConnect) + { + OnBackwardConnect?.Invoke(mUID, mTunnelID, mIdx, this); + } + else + { + //连接失败 + NetworkDeBugLog("连接失败!"); + } + } + + public void NetworkDeBugLog(string str) + { + OnBackwardLogOut?.Invoke(1 ,"NetCoreDebug >> " + str); + } + + /// + /// 接受包回调 + /// + /// 协议ID + /// 错误编号 + /// 业务数据 + public void GetDataCallBack(byte[] data) + { + //NetworkDeBugLog("收到消息 数据长度=>" + data.Length); + try + { + //记录接收数据长度 + mReciveAllLenght += data.Length; + //抛出网络数据 + OnBackwardDataCallBack?.Invoke(mUID, mTunnelID, mIdx, data); + } + catch (Exception ex) + { + NetworkDeBugLog("逻辑处理错误:" + ex.ToString()); + } + + } + + /// + /// 关闭连接 + /// + void OnConnectClose() + { + NetworkDeBugLog("OnConnectClose"); + OnBackwardDisconnect?.Invoke(mUID, mTunnelID,mIdx,this); + } + + public void Release() + { + OnBackwardLogOut -= OnBackwardLogOut; + OnBackwardConnect -= OnBackwardConnect; + OnBackwardDisconnect -= OnBackwardDisconnect; + OnBackwardDataCallBack -= OnBackwardDataCallBack; + } + } +} diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapter.cs b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapter.cs new file mode 100644 index 0000000..2bce95e --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapter.cs @@ -0,0 +1,94 @@ +using System.IO; +using System.IO.Compression; + +namespace NoSugarNet.Adapter.DataHelper +{ + public enum E_CompressAdapter + { + //不压缩 + None = 0, + //GIPZ + GZIP_Plan1 = 1, + } + + /// + /// 压缩适配器 + /// + public class CompressAdapter + { + IDataCompress mIDataCompress; + public CompressAdapter(E_CompressAdapter type) + { + switch (type) + { + //不压缩 + case E_CompressAdapter.None: + mIDataCompress = new NoCompress(); + break; + //GZIP Plan1 + case E_CompressAdapter.GZIP_Plan1: + mIDataCompress = new GZipCompress(); + break; + //TODO 其他压缩对比 + //…… + default: + mIDataCompress = new NoCompress(); + break; + } + } + + public byte[] Compress(byte[] data) + { + return mIDataCompress.Compress(data); + } + public byte[] Decompress(byte[] data) + { + return mIDataCompress.Decompress(data); + } + } + + + public interface IDataCompress + { + byte[] Compress(byte[] data); + byte[] Decompress(byte[] data); + } + + public class NoCompress : IDataCompress + { + public byte[] Compress(byte[] data) + { + return data; + } + public byte[] Decompress(byte[] data) + { + return data; + } + } + + public class GZipCompress : IDataCompress + { + public byte[] Compress(byte[] data) + { + using (var compressedStream = new MemoryStream()) + using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress)) + { + zipStream.Write(data, 0, data.Length); + zipStream.Close(); + return compressedStream.ToArray(); + } + } + + public byte[] Decompress(byte[] data) + { + using (var compressedStream = new MemoryStream(data)) + using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) + using (var resultStream = new MemoryStream()) + { + zipStream.CopyTo(resultStream); + return resultStream.ToArray(); + } + } + } + +} diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapterSelector.cs b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapterSelector.cs new file mode 100644 index 0000000..8699761 --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/DataHelper/CompressAdapterSelector.cs @@ -0,0 +1,19 @@ +using NoSugarNet.Adapter.DataHelper; +using System.Collections.Generic; + +namespace NoSugarNet.Adapter.DataHelper +{ + public static class CompressAdapterSelector + { + static Dictionary mDictAdapter = new Dictionary(); + + public static CompressAdapter Adapter(E_CompressAdapter adptType) + { + if(mDictAdapter.ContainsKey(adptType)) + return mDictAdapter[adptType]; + + mDictAdapter[adptType] = new CompressAdapter(adptType); + return mDictAdapter[adptType]; + } + } +} \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/ForwardLocalListener.cs b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/ForwardLocalListener.cs new file mode 100644 index 0000000..030cd70 --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/ForwardLocalListener.cs @@ -0,0 +1,347 @@ +using HaoYueNet.ServerNetwork.Standard2; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Sockets; + +namespace NoSugarNet.Adapter +{ + public class ForwardLocalListener : TcpSaeaServer_SourceMode + { + public byte mTunnelID; + public long mReciveAllLenght; + public long mSendAllLenght; + public long currSeed; + public long mUid; + static long Seed; + + public enum AdptLogLevel + { + Debug, + Info, + Warning, + Error + } + + public delegate void OnLogOutHandler(int LogLevel,string Msg); + public delegate void OnClientLocalConnectHandler(long UID, byte tunnelId, byte _Idx); + public delegate void OnClientLocalDisconnectHandler(long UID, byte tunnelId, byte _Idx); + public delegate void OnClientTunnelDataCallBackHandler(long UID, byte tunnelId, byte Idx, byte[] data); + + public event OnLogOutHandler OnForwardLogOut; + public event OnClientLocalConnectHandler OnClientLocalConnect; + public event OnClientLocalDisconnectHandler OnClientLocalDisconnect; + public event OnClientTunnelDataCallBackHandler OnClientTunnelDataCallBack; + + public ForwardLocalListener(int numConnections, int receiveBufferSize, byte TunnelID, long mUid) + : base(numConnections, receiveBufferSize) + { + OnClientNumberChange += ClientNumberChange; + OnReceive += ReceiveData; + OnDisconnected += OnDisconnect; + OnNetLog += OnShowNetLog; + + mTunnelID = TunnelID; + + currSeed = Seed++; + this.mUid = mUid; + } + + + + public event OnLogOutHandler OnForwardLogOut2; + + public void BandEvent( + OnLogOutHandler _OnLogOut, + OnClientLocalConnectHandler _OnClientLocalConnect, + OnClientLocalDisconnectHandler _OnClientLocalDisconnect, + OnClientTunnelDataCallBackHandler _ClientTunnelDataCall + ) + { + OnForwardLogOut += _OnLogOut; + OnClientLocalConnect += _OnClientLocalConnect; + OnClientLocalDisconnect += _OnClientLocalDisconnect; + OnClientTunnelDataCallBack += _ClientTunnelDataCall; + } + + public void StartListener(uint port) + { + Init(); + Start(new IPEndPoint(IPAddress.Any.Address, (int)port)); + } + + private void ClientNumberChange(int num, AsyncUserToken token) + { + OnForwardLogOut?.Invoke((int)AdptLogLevel.Info, "Client数发生变化"); + //增加连接数stsc + if (num > 0) + { + int Idx = AddDictSocket(token.Socket); + if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInf)) + { + OnClientLocalConnect?.Invoke(mUid, mTunnelID, (byte)Idx); + } + } + } + + /// + /// 通过下标发送 + /// + /// + /// + public void SendSocketByIdx(int Idx, byte[] data) + { + if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) + { + mSendAllLenght += data.Length; + SendToSocket(_localClientInfo._socket, data); + } + //TODO连接前缓存数据 + } + + /// + /// 接受包回调 + /// + /// 协议ID + /// 错误编号 + /// 业务数据 + private void ReceiveData(AsyncUserToken token, byte[] data) + { + DataCallBack(token.Socket, data); + } + + public void DataCallBack(Socket sk, byte[] data) + { + //AppNoSugarNet.log.Info("收到消息 数据长度=>" + data.Length); + //记录接受长度 + mReciveAllLenght += data.Length; + if (!GetSocketIdxBySocket(sk, out int Idx)) + return; + try + { + //抛出网络数据 + OnClientTunnelDataCallBack?.Invoke(mUid, mTunnelID, (byte)Idx, data); + } + catch (Exception ex) + { + OnForwardLogOut?.Invoke((int)AdptLogLevel.Error,"逻辑处理错误:" + ex.ToString()); + } + } + + public void CloseConnectByIdx(byte Idx) + { + if (GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) + { + //把未发送消息队列回收了 + while (_localClientInfo.msgQueue.Count > 0) + { + IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); + MsgQueuePool._MsgPool.Enqueue(msg); + } + + _localClientInfo._socket.Shutdown(SocketShutdown.Both); + } + } + + /// + /// 断开连接 + /// + /// + public void OnDisconnect(AsyncUserToken token) + { + OnForwardLogOut?.Invoke((int)AdptLogLevel.Info,"断开连接"); + + if (!GetSocketIdxBySocket(token.Socket, out int Idx)) + return; + + OnClientLocalDisconnect?.Invoke(mUid, mTunnelID, (byte)Idx); + RemoveDictSocket(token.Socket); + } + + public void OnShowNetLog(string msg) + { + OnForwardLogOut?.Invoke((int)AdptLogLevel.Info, msg); + } + + #region 一个轻量级无用户连接管理 + Dictionary DictSocketHandle2Idx = new Dictionary(); + Dictionary DictIdx2LocalClientInfo = new Dictionary(); + int mSeedIdx = 0; + List FreeIdxs = new List(); + public class LocalClientInfo + { + public Socket _socket; + public bool bRemoteConnect; + public bool bLocalConnect => _socket.Connected; + public Queue msgQueue = new Queue(); + } + + public Dictionary GetDictIdx2LocalClientInfo() + { + return DictIdx2LocalClientInfo; + } + + int GetNextIdx() + { + if (FreeIdxs.Count > 0) + { + int Idx = FreeIdxs[0]; + FreeIdxs.RemoveAt(0); + return Idx; + } + return mSeedIdx++; + } + + void ResetFree() + { + FreeIdxs.Clear(); + mSeedIdx = 0; + } + + /// + /// 追加Socket返回下标 + /// + /// + /// + public int AddDictSocket(Socket socket) + { + if (socket == null) + return -1; + lock (DictSocketHandle2Idx) + { + int Idx = GetNextIdx(); + DictSocketHandle2Idx[socket.Handle] = Idx; + DictIdx2LocalClientInfo[Idx] = new LocalClientInfo() { _socket = socket,bRemoteConnect = false}; + OnForwardLogOut?.Invoke((int)AdptLogLevel.Debug, $"AddDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); + return Idx; + } + } + + public void RemoveDictSocket(Socket socket) + { + if (socket == null) + return; + lock (DictSocketHandle2Idx) + { + if (!DictSocketHandle2Idx.ContainsKey(socket.Handle)) + return; + int Idx = DictSocketHandle2Idx[socket.Handle]; + FreeIdxs.Add(Idx); + if (DictIdx2LocalClientInfo.ContainsKey(Idx)) + DictIdx2LocalClientInfo.Remove(Idx); + DictSocketHandle2Idx.Remove(socket.Handle); + OnForwardLogOut?.Invoke((int)AdptLogLevel.Debug, $"RemoveDictSocket mTunnelID->{mTunnelID} Idx->{Idx} socket.Handle{socket.Handle}"); + } + } + + bool GetSocketByIdx(int Idx, out LocalClientInfo _localClientInfo) + { + if (!DictIdx2LocalClientInfo.ContainsKey(Idx)) + { + _localClientInfo = null; + return false; + } + + _localClientInfo = DictIdx2LocalClientInfo[Idx]; + return true; + } + + public bool GetSocketIdxBySocket(Socket _socket, out int Idx) + { + if (_socket == null) + { + Idx = -1; + return false; + } + + if (!DictSocketHandle2Idx.ContainsKey(_socket.Handle)) + { + Idx = -1; + return false; + } + + Idx = DictSocketHandle2Idx[_socket.Handle]; + return true; + } + + public bool CheckRemoteConnect(int Idx) + { + if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) + return false; + return _localClientInfo.bRemoteConnect; + } + + public void SetRemoteConnectd(int Idx,bool bConnected) + { + if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) + return; + if (bConnected) + OnForwardLogOut?.Invoke((int)AdptLogLevel.Info,"远端本地连接已连接!!!!"); + else + OnForwardLogOut?.Invoke((int)AdptLogLevel.Info, "远端本地连接已断开连接!!!!"); + _localClientInfo.bRemoteConnect = bConnected; + } + + public void StopAllLocalClient() + { + lock (DictIdx2LocalClientInfo) + { + int[] Idxs = DictIdx2LocalClientInfo.Keys.ToArray(); + for (int i = 0; i < Idxs.Length; i++) + { + CloseConnectByIdx((byte)Idxs[i]); + } + DictIdx2LocalClientInfo.Clear(); + DictSocketHandle2Idx.Clear(); + ResetFree(); + } + } + + public void StopWithClear() + { + base.Stop(); + //清理事件 + OnForwardLogOut -= OnForwardLogOut; + OnClientLocalConnect -= OnClientLocalConnect; + OnClientLocalDisconnect -= OnClientLocalDisconnect; + OnClientTunnelDataCallBack -= OnClientTunnelDataCallBack; + } + + #endregion + + + #region 缓存 + public void EnqueueIdxWithMsg(byte Idx, byte[] data) + { + if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo)) + return; + + IdxWithMsg Msg = MsgQueuePool._MsgPool.Dequeue(); + Msg.Idx = Idx; + Msg.data = data; + _localClientInfo.msgQueue.Enqueue(Msg); + } + public bool GetDictMsgQueue(byte Idx,out List MsgList) + { + if (!GetSocketByIdx(Idx, out LocalClientInfo _localClientInfo) || _localClientInfo.msgQueue.Count < 1) + { + MsgList = null; + return false; + } + + MsgList = new List(); + lock (_localClientInfo.msgQueue) + { + while (_localClientInfo.msgQueue.Count > 0) + { + IdxWithMsg msg = _localClientInfo.msgQueue.Dequeue(); + MsgList.Add(msg); + } + return true; + } + } + #endregion + } + +} diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/LocalMsgQueuePool.cs b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/LocalMsgQueuePool.cs new file mode 100644 index 0000000..c33616c --- /dev/null +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.Adapter/LocalMsgQueuePool.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; + +namespace NoSugarNet.Adapter +{ + public class IdxWithMsg + { + public byte Idx; + public byte[] data; + } + + public class MsgQueuePool + { + public static MsgQueuePool _MsgPool = new MsgQueuePool(1000); + + Queue msg_pool; + + public MsgQueuePool(int capacity) + { + msg_pool = new Queue(capacity); + } + + /// + /// 向 Queue 的末尾添加一个对象。 + /// + /// + public void Enqueue(IdxWithMsg item) + { + lock (msg_pool) + { + item.Idx = 0; + item.data = null; + msg_pool.Enqueue(item); + } + } + + //移除并返回在 Queue 的开头的对象。 + public IdxWithMsg Dequeue() + { + lock (msg_pool) + { + if(msg_pool.Count > 0) + return msg_pool.Dequeue(); + return new IdxWithMsg(); + } + } + + public int Count + { + get { return msg_pool.Count; } + } + + public void Clear() + { + msg_pool.Clear(); + } + } +} diff --git a/NoSugarNet.ClientCore.Standard2/NoSugarNet.ClientCore.Standard2.csproj b/NoSugarNet.ClientCore.Standard2/NoSugarNet.ClientCore.Standard2.csproj index 59561e8..68f335e 100644 --- a/NoSugarNet.ClientCore.Standard2/NoSugarNet.ClientCore.Standard2.csproj +++ b/NoSugarNet.ClientCore.Standard2/NoSugarNet.ClientCore.Standard2.csproj @@ -13,8 +13,8 @@ ..\Lib\Google.Protobuf.dll - - ..\Lib\NetLib_Standard2\HaoYueNet.ClientNetworkNet.Standard2.dll + + ..\Lib\NetLib_Standard2\HaoYueNet.ClientNetwork.Standard2.dll ..\Lib\NetLib_Standard2\HaoYueNet.ServerNetwork.Standard2.dll diff --git a/NoSugarNet.ClientCore.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user b/NoSugarNet.ClientCore.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user index 040aa3b..a77223e 100644 --- a/NoSugarNet.ClientCore.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user +++ b/NoSugarNet.ClientCore.Standard2/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121. --> - True|2024-04-15T06:51:39.2435225Z;True|2024-04-15T14:51:19.4250865+08:00;True|2024-04-15T14:49:22.9829361+08:00; + True|2024-10-18T08:27:43.7757014Z||;True|2024-10-18T16:15:48.7317736+08:00||;True|2024-10-18T15:37:40.8031046+08:00||;True|2024-10-18T15:36:28.8043094+08:00||;True|2024-04-15T14:51:39.2435225+08:00||;True|2024-04-15T14:51:19.4250865+08:00||;True|2024-04-15T14:49:22.9829361+08:00||; \ No newline at end of file diff --git a/NoSugarNet.ClientCore.Standard2/Protobuf/ProtobufNoSugar.cs b/NoSugarNet.ClientCore.Standard2/Protobuf/ProtobufNoSugar.cs index dce38be..dd89e45 100644 --- a/NoSugarNet.ClientCore.Standard2/Protobuf/ProtobufNoSugar.cs +++ b/NoSugarNet.ClientCore.Standard2/Protobuf/ProtobufNoSugar.cs @@ -28,51 +28,51 @@ namespace AxibugProtobuf { "UHJvdG9idWZfTG9naW4SLAoJbG9naW5UeXBlGAEgASgOMhkuQXhpYnVnUHJv", "dG9idWYuTG9naW5UeXBlEi4KCmRldmljZVR5cGUYAiABKA4yGi5BeGlidWdQ", "cm90b2J1Zi5EZXZpY2VUeXBlEg8KB0FjY291bnQYAyABKAkSEAoIUGFzc3dv", - "cmQYBCABKAkifwoTUHJvdG9idWZfTG9naW5fUkVTUBINCgVUb2tlbhgBIAEo", - "CRIVCg1MYXN0TG9naW5EYXRlGAIgASgJEg8KB1JlZ0RhdGUYAyABKAkSMQoG", - "U3RhdHVzGAQgASgOMiEuQXhpYnVnUHJvdG9idWYuTG9naW5SZXN1bHRTdGF0", - "dXMiYAoNUHJvdG9idWZfQ2ZncxIbChNDb21wcmVzc0FkYXB0ZXJUeXBlGAEg", - "ASgFEjIKBGNmZ3MYAiADKAsyJC5BeGlidWdQcm90b2J1Zi5Qcm90b2J1Zl9D", - "ZmdzX1NpbmdsZSI2ChRQcm90b2J1Zl9DZmdzX1NpbmdsZRIQCghUdW5uZWxJ", - "RBgBIAEoDRIMCgRQb3J0GAIgASgFIiMKEFByb3RvYnVmX0NoYXRNc2cSDwoH", - "Q2hhdE1zZxgBIAEoCSJIChVQcm90b2J1Zl9DaGF0TXNnX1JFU1ASEAoITmlj", - "a05hbWUYASABKAkSDwoHQ2hhdE1zZxgCIAEoCRIMCgREYXRlGAMgASgDIjUK", - "FFByb3RvYnVmX0MyU19Db25uZWN0EhAKCFR1bm5lbElEGAEgASgNEgsKA0lk", - "eBgCIAEoDSJIChRQcm90b2J1Zl9TMkNfQ29ubmVjdBIQCghUdW5uZWxJRBgB", - "IAEoDRILCgNJZHgYAiABKA0SEQoJQ29ubmVjdGVkGAMgASgNIjgKF1Byb3Rv", - "YnVmX0MyU19EaXNjb25uZWN0EhAKCFR1bm5lbElEGAEgASgNEgsKA0lkeBgC", - "IAEoDSI4ChdQcm90b2J1Zl9TMkNfRGlzY29ubmVjdBIQCghUdW5uZWxJRBgB", - "IAEoDRILCgNJZHgYAiABKA0iTgoRUHJvdG9idWZfQzJTX0RBVEESEAoIVHVu", + "cmQYBCABKAkijAEKE1Byb3RvYnVmX0xvZ2luX1JFU1ASDQoFVG9rZW4YASAB", + "KAkSFQoNTGFzdExvZ2luRGF0ZRgCIAEoCRIPCgdSZWdEYXRlGAMgASgJEjEK", + "BlN0YXR1cxgEIAEoDjIhLkF4aWJ1Z1Byb3RvYnVmLkxvZ2luUmVzdWx0U3Rh", + "dHVzEgsKA1VJRBgFIAEoAyJgCg1Qcm90b2J1Zl9DZmdzEhsKE0NvbXByZXNz", + "QWRhcHRlclR5cGUYASABKAUSMgoEY2ZncxgCIAMoCzIkLkF4aWJ1Z1Byb3Rv", + "YnVmLlByb3RvYnVmX0NmZ3NfU2luZ2xlIjYKFFByb3RvYnVmX0NmZ3NfU2lu", + "Z2xlEhAKCFR1bm5lbElEGAEgASgNEgwKBFBvcnQYAiABKAUiIwoQUHJvdG9i", + "dWZfQ2hhdE1zZxIPCgdDaGF0TXNnGAEgASgJIkgKFVByb3RvYnVmX0NoYXRN", + "c2dfUkVTUBIQCghOaWNrTmFtZRgBIAEoCRIPCgdDaGF0TXNnGAIgASgJEgwK", + "BERhdGUYAyABKAMiSwoXUHJvdG9idWZfVHVubmVsX0Nvbm5lY3QSEAoIVHVu", + "bmVsSUQYASABKA0SCwoDSWR4GAIgASgNEhEKCUNvbm5lY3RlZBgDIAEoDSI7", + "ChpQcm90b2J1Zl9UdW5uZWxfRGlzY29ubmVjdBIQCghUdW5uZWxJRBgBIAEo", + "DRILCgNJZHgYAiABKA0iUQoUUHJvdG9idWZfVHVubmVsX0RBVEESEAoIVHVu", "bmVsSUQYASABKA0SCwoDSWR4GAIgASgNEhoKEkh1bnRlck5ldENvcmVfRGF0", - "YRgDIAEoDCJOChFQcm90b2J1Zl9TMkNfREFUQRIQCghUdW5uZWxJRBgBIAEo", - "DRILCgNJZHgYAiABKA0SGgoSSHVudGVyTmV0Q29yZV9EYXRhGAMgASgMKvoB", - "CglDb21tYW5kSUQSDgoKQ01EX0RFRkFVTBAAEg4KCUNNRF9MT0dJThDRDxIN", - "CghDTURfQ0ZHUxC5FxIQCgtDTURfQ0hBVE1TRxChHxIbChZDTURfVFVOTkVM", - "X0MyU19DT05ORUNUEIgnEhsKFkNNRF9UVU5ORUxfUzJDX0NPTk5FQ1QQiScS", - "HgoZQ01EX1RVTk5FTF9DMlNfRElTQ09OTkVDVBCKJxIeChlDTURfVFVOTkVM", - "X1MyQ19ESVNDT05ORUNUEIsnEhgKE0NNRF9UVU5ORUxfQzJTX0RBVEEQjCcS", - "GAoTQ01EX1RVTk5FTF9TMkNfREFUQRCNJyorCglFcnJvckNvZGUSEAoMRVJS", - "T1JfREVGQVVMEAASDAoIRVJST1JfT0sQASo+CglMb2dpblR5cGUSDwoLQmFz", - "ZURlZmF1bHQQABIOCgpIYW9ZdWVBdXRoEAESBwoDQkYzEAMSBwoDQkY0EAQq", - "SwoKRGV2aWNlVHlwZRIWChJEZXZpY2VUeXBlX0RlZmF1bHQQABIGCgJQQxAB", - "EgsKB0FuZHJvaWQQAhIHCgNJT1MQAxIHCgNQU1YQBCpOChFMb2dpblJlc3Vs", - "dFN0YXR1cxIhCh1Mb2dpblJlc3VsdFN0YXR1c19CYXNlRGVmYXVsdBAAEgYK", - "Ak9LEAESDgoKQWNjb3VudEVychACQgJIAWIGcHJvdG8z")); + "YRgDIAEoDCqlBAoJQ29tbWFuZElEEg4KCkNNRF9ERUZBVUwQABIOCglDTURf", + "TE9HSU4Q0Q8SFAoPQ01EX1NFUlZFUl9DRkdTELkXEhQKD0NNRF9DTElFTlRf", + "Q0ZHUxC6FxIQCgtDTURfQ0hBVE1TRxChHxIjCh5DTURfVFVOTkVMX0MyU19G", + "T1JXQVJEX0NPTk5FQ1QQiCcSIwoeQ01EX1RVTk5FTF9TMkNfRk9SV0FSRF9D", + "T05ORUNUEIknEiYKIUNNRF9UVU5ORUxfQzJTX0ZPUldBUkRfRElTQ09OTkVD", + "VBCKJxImCiFDTURfVFVOTkVMX1MyQ19GT1JXQVJEX0RJU0NPTk5FQ1QQiycS", + "IAobQ01EX1RVTk5FTF9DMlNfRk9SV0FSRF9EQVRBEIwnEiAKG0NNRF9UVU5O", + "RUxfUzJDX0ZPUldBUkRfREFUQRCNJxIjCh5DTURfVFVOTkVMX0MyU19SRVZF", + "UlNFX0NPTk5FQ1QQ8C4SIwoeQ01EX1RVTk5FTF9TMkNfUkVWRVJTRV9DT05O", + "RUNUEPEuEiYKIUNNRF9UVU5ORUxfQzJTX1JFVkVSU0VfRElTQ09OTkVDVBDy", + "LhImCiFDTURfVFVOTkVMX1MyQ19SRVZFUlNFX0RJU0NPTk5FQ1QQ8y4SIAob", + "Q01EX1RVTk5FTF9DMlNfUkVWRVJTRV9EQVRBEPQuEiAKG0NNRF9UVU5ORUxf", + "UzJDX1JFVkVSU0VfREFUQRD1LiorCglFcnJvckNvZGUSEAoMRVJST1JfREVG", + "QVVMEAASDAoIRVJST1JfT0sQASo+CglMb2dpblR5cGUSDwoLQmFzZURlZmF1", + "bHQQABIOCgpIYW9ZdWVBdXRoEAESBwoDQkYzEAMSBwoDQkY0EAQqSwoKRGV2", + "aWNlVHlwZRIWChJEZXZpY2VUeXBlX0RlZmF1bHQQABIGCgJQQxABEgsKB0Fu", + "ZHJvaWQQAhIHCgNJT1MQAxIHCgNQU1YQBCpOChFMb2dpblJlc3VsdFN0YXR1", + "cxIhCh1Mb2dpblJlc3VsdFN0YXR1c19CYXNlRGVmYXVsdBAAEgYKAk9LEAES", + "DgoKQWNjb3VudEVychACQgJIAWIGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::AxibugProtobuf.CommandID), typeof(global::AxibugProtobuf.ErrorCode), typeof(global::AxibugProtobuf.LoginType), typeof(global::AxibugProtobuf.DeviceType), typeof(global::AxibugProtobuf.LoginResultStatus), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Login), global::AxibugProtobuf.Protobuf_Login.Parser, new[]{ "LoginType", "DeviceType", "Account", "Password" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Login_RESP), global::AxibugProtobuf.Protobuf_Login_RESP.Parser, new[]{ "Token", "LastLoginDate", "RegDate", "Status" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Login_RESP), global::AxibugProtobuf.Protobuf_Login_RESP.Parser, new[]{ "Token", "LastLoginDate", "RegDate", "Status", "UID" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Cfgs), global::AxibugProtobuf.Protobuf_Cfgs.Parser, new[]{ "CompressAdapterType", "Cfgs" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Cfgs_Single), global::AxibugProtobuf.Protobuf_Cfgs_Single.Parser, new[]{ "TunnelID", "Port" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_ChatMsg), global::AxibugProtobuf.Protobuf_ChatMsg.Parser, new[]{ "ChatMsg" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_ChatMsg_RESP), global::AxibugProtobuf.Protobuf_ChatMsg_RESP.Parser, new[]{ "NickName", "ChatMsg", "Date" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_C2S_Connect), global::AxibugProtobuf.Protobuf_C2S_Connect.Parser, new[]{ "TunnelID", "Idx" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_S2C_Connect), global::AxibugProtobuf.Protobuf_S2C_Connect.Parser, new[]{ "TunnelID", "Idx", "Connected" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_C2S_Disconnect), global::AxibugProtobuf.Protobuf_C2S_Disconnect.Parser, new[]{ "TunnelID", "Idx" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_S2C_Disconnect), global::AxibugProtobuf.Protobuf_S2C_Disconnect.Parser, new[]{ "TunnelID", "Idx" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_C2S_DATA), global::AxibugProtobuf.Protobuf_C2S_DATA.Parser, new[]{ "TunnelID", "Idx", "HunterNetCoreData" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_S2C_DATA), global::AxibugProtobuf.Protobuf_S2C_DATA.Parser, new[]{ "TunnelID", "Idx", "HunterNetCoreData" }, null, null, null, null) + new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Tunnel_Connect), global::AxibugProtobuf.Protobuf_Tunnel_Connect.Parser, new[]{ "TunnelID", "Idx", "Connected" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Tunnel_Disconnect), global::AxibugProtobuf.Protobuf_Tunnel_Disconnect.Parser, new[]{ "TunnelID", "Idx" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::AxibugProtobuf.Protobuf_Tunnel_DATA), global::AxibugProtobuf.Protobuf_Tunnel_DATA.Parser, new[]{ "TunnelID", "Idx", "HunterNetCoreData" }, null, null, null, null) })); } #endregion @@ -91,35 +91,63 @@ namespace AxibugProtobuf { /// ///配置信息 下行 对应 Protobuf_Cfgs /// - [pbr::OriginalName("CMD_CFGS")] CmdCfgs = 3001, + [pbr::OriginalName("CMD_SERVER_CFGS")] CmdServerCfgs = 3001, + /// + ///配置信息 上行 对应 Protobuf_Cfgs + /// + [pbr::OriginalName("CMD_CLIENT_CFGS")] CmdClientCfgs = 3002, /// ///广播信息上行 | 下行 对应 Protobuf_ChatMsg | Protobuf_ChatMsg_RESP /// [pbr::OriginalName("CMD_CHATMSG")] CmdChatmsg = 4001, /// - ///客户端告知服务端 客户端本地连接建立 上行 Protobuf_C2S_Connect + ///正向代理,客户端告知服务端 客户端本地连接建立 上行 Protobuf_Tunnel_Connect /// - [pbr::OriginalName("CMD_TUNNEL_C2S_CONNECT")] CmdTunnelC2SConnect = 5000, + [pbr::OriginalName("CMD_TUNNEL_C2S_FORWARD_CONNECT")] CmdTunnelC2SForwardConnect = 5000, /// - ///服务端告知客户端 服务端本地连接建立 下行 Protobuf_S2C_Connect + ///正向代理,服务端告知客户端 服务端本地连接建立 下行 Protobuf_Tunnel_Connect /// - [pbr::OriginalName("CMD_TUNNEL_S2C_CONNECT")] CmdTunnelS2CConnect = 5001, + [pbr::OriginalName("CMD_TUNNEL_S2C_FORWARD_CONNECT")] CmdTunnelS2CForwardConnect = 5001, /// - ///客户端告知服务端 客户端本地连接断开 上行 Protobuf_C2S_Disconnect + ///正向代理,客户端告知服务端 客户端本地连接断开 上行 Protobuf_Tunnel_Disconnect /// - [pbr::OriginalName("CMD_TUNNEL_C2S_DISCONNECT")] CmdTunnelC2SDisconnect = 5002, + [pbr::OriginalName("CMD_TUNNEL_C2S_FORWARD_DISCONNECT")] CmdTunnelC2SForwardDisconnect = 5002, /// - ///服务端告知客户端 服务端本地连接断开 下行 Protobuf_S2C_Disconnect + ///正向代理,服务端告知客户端 服务端本地连接断开 下行 Protobuf_Tunnel_Disconnect /// - [pbr::OriginalName("CMD_TUNNEL_S2C_DISCONNECT")] CmdTunnelS2CDisconnect = 5003, + [pbr::OriginalName("CMD_TUNNEL_S2C_FORWARD_DISCONNECT")] CmdTunnelS2CForwardDisconnect = 5003, /// - ///客户端投递本地TCP通讯数据包 上行 Protobuf_C2S_DATA + ///正向代理,客户端投递本地TCP通讯数据包 上行 Protobuf_Tunnel_DATA /// - [pbr::OriginalName("CMD_TUNNEL_C2S_DATA")] CmdTunnelC2SData = 5004, + [pbr::OriginalName("CMD_TUNNEL_C2S_FORWARD_DATA")] CmdTunnelC2SForwardData = 5004, /// - ///服务端投递本地TCP通讯数据包 下行 Protobuf_S2C_DATA + ///正向代理,服务端投递本地TCP通讯数据包 下行 Protobuf_Tunnel_DATA /// - [pbr::OriginalName("CMD_TUNNEL_S2C_DATA")] CmdTunnelS2CData = 5005, + [pbr::OriginalName("CMD_TUNNEL_S2C_FORWARD_DATA")] CmdTunnelS2CForwardData = 5005, + /// + ///反向代理,客户端告知服务端 客户端本地连接建立 上行 Protobuf_Tunnel_Connect + /// + [pbr::OriginalName("CMD_TUNNEL_C2S_REVERSE_CONNECT")] CmdTunnelC2SReverseConnect = 6000, + /// + ///反向代理,服务端告知客户端 服务端本地连接建立 下行 Protobuf_Tunnel_Connect + /// + [pbr::OriginalName("CMD_TUNNEL_S2C_REVERSE_CONNECT")] CmdTunnelS2CReverseConnect = 6001, + /// + ///反向代理,客户端告知服务端 客户端本地连接断开 上行 Protobuf_Tunnel_Disconnect + /// + [pbr::OriginalName("CMD_TUNNEL_C2S_REVERSE_DISCONNECT")] CmdTunnelC2SReverseDisconnect = 6002, + /// + ///反向代理,服务端告知客户端 服务端本地连接断开 下行 Protobuf_Tunnel_Disconnect + /// + [pbr::OriginalName("CMD_TUNNEL_S2C_REVERSE_DISCONNECT")] CmdTunnelS2CReverseDisconnect = 6003, + /// + ///反向代理,客户端投递本地TCP通讯数据包 上行 Protobuf_Tunnel_DATA + /// + [pbr::OriginalName("CMD_TUNNEL_C2S_REVERSE_DATA")] CmdTunnelC2SReverseData = 6004, + /// + ///反向代理,服务端投递本地TCP通讯数据包 下行 Protobuf_Tunnel_DATA + /// + [pbr::OriginalName("CMD_TUNNEL_S2C_REVERSE_DATA")] CmdTunnelS2CReverseData = 6005, } public enum ErrorCode { @@ -497,6 +525,7 @@ namespace AxibugProtobuf { lastLoginDate_ = other.lastLoginDate_; regDate_ = other.regDate_; status_ = other.status_; + uID_ = other.uID_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -561,6 +590,17 @@ namespace AxibugProtobuf { } } + /// Field number for the "UID" field. + public const int UIDFieldNumber = 5; + private long uID_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long UID { + get { return uID_; } + set { + uID_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as Protobuf_Login_RESP); @@ -578,6 +618,7 @@ namespace AxibugProtobuf { if (LastLoginDate != other.LastLoginDate) return false; if (RegDate != other.RegDate) return false; if (Status != other.Status) return false; + if (UID != other.UID) return false; return Equals(_unknownFields, other._unknownFields); } @@ -588,6 +629,7 @@ namespace AxibugProtobuf { if (LastLoginDate.Length != 0) hash ^= LastLoginDate.GetHashCode(); if (RegDate.Length != 0) hash ^= RegDate.GetHashCode(); if (Status != global::AxibugProtobuf.LoginResultStatus.BaseDefault) hash ^= Status.GetHashCode(); + if (UID != 0L) hash ^= UID.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -620,6 +662,10 @@ namespace AxibugProtobuf { output.WriteRawTag(32); output.WriteEnum((int) Status); } + if (UID != 0L) { + output.WriteRawTag(40); + output.WriteInt64(UID); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -645,6 +691,10 @@ namespace AxibugProtobuf { output.WriteRawTag(32); output.WriteEnum((int) Status); } + if (UID != 0L) { + output.WriteRawTag(40); + output.WriteInt64(UID); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -666,6 +716,9 @@ namespace AxibugProtobuf { if (Status != global::AxibugProtobuf.LoginResultStatus.BaseDefault) { size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); } + if (UID != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(UID); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -689,6 +742,9 @@ namespace AxibugProtobuf { if (other.Status != global::AxibugProtobuf.LoginResultStatus.BaseDefault) { Status = other.Status; } + if (other.UID != 0L) { + UID = other.UID; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -719,6 +775,10 @@ namespace AxibugProtobuf { Status = (global::AxibugProtobuf.LoginResultStatus) input.ReadEnum(); break; } + case 40: { + UID = input.ReadInt64(); + break; + } } } #endif @@ -749,6 +809,10 @@ namespace AxibugProtobuf { Status = (global::AxibugProtobuf.LoginResultStatus) input.ReadEnum(); break; } + case 40: { + UID = input.ReadInt64(); + break; + } } } } @@ -1610,15 +1674,15 @@ namespace AxibugProtobuf { } - public sealed partial class Protobuf_C2S_Connect : pb::IMessage + public sealed partial class Protobuf_Tunnel_Connect : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage #endif { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_C2S_Connect()); + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_Tunnel_Connect()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } + public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { @@ -1631,228 +1695,14 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Connect() { + public Protobuf_Tunnel_Connect() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Connect(Protobuf_C2S_Connect other) : this() { - tunnelID_ = other.tunnelID_; - idx_ = other.idx_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Connect Clone() { - return new Protobuf_C2S_Connect(this); - } - - /// Field number for the "TunnelID" field. - public const int TunnelIDFieldNumber = 1; - private uint tunnelID_; - /// - ///TunnelID - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint TunnelID { - get { return tunnelID_; } - set { - tunnelID_ = value; - } - } - - /// Field number for the "Idx" field. - public const int IdxFieldNumber = 2; - private uint idx_; - /// - ///单个隧道连接下标 - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint Idx { - get { return idx_; } - set { - idx_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Protobuf_C2S_Connect); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_C2S_Connect other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TunnelID != other.TunnelID) return false; - if (Idx != other.Idx) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (TunnelID != 0) hash ^= TunnelID.GetHashCode(); - if (Idx != 0) hash ^= Idx.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (TunnelID != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TunnelID); - } - if (Idx != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Idx); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_C2S_Connect other) { - if (other == null) { - return; - } - if (other.TunnelID != 0) { - TunnelID = other.TunnelID; - } - if (other.Idx != 0) { - Idx = other.Idx; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - } - #endif - - } - - public sealed partial class Protobuf_S2C_Connect : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_S2C_Connect()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::AxibugProtobuf.ProtobufNoSugarReflection.Descriptor.MessageTypes[7]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Connect() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Connect(Protobuf_S2C_Connect other) : this() { + public Protobuf_Tunnel_Connect(Protobuf_Tunnel_Connect other) : this() { tunnelID_ = other.tunnelID_; idx_ = other.idx_; connected_ = other.connected_; @@ -1860,8 +1710,8 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Connect Clone() { - return new Protobuf_S2C_Connect(this); + public Protobuf_Tunnel_Connect Clone() { + return new Protobuf_Tunnel_Connect(this); } /// Field number for the "TunnelID" field. @@ -1908,11 +1758,11 @@ namespace AxibugProtobuf { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { - return Equals(other as Protobuf_S2C_Connect); + return Equals(other as Protobuf_Tunnel_Connect); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_S2C_Connect other) { + public bool Equals(Protobuf_Tunnel_Connect other) { if (ReferenceEquals(other, null)) { return false; } @@ -2005,7 +1855,7 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_S2C_Connect other) { + public void MergeFrom(Protobuf_Tunnel_Connect other) { if (other == null) { return; } @@ -2077,15 +1927,229 @@ namespace AxibugProtobuf { } - public sealed partial class Protobuf_C2S_Disconnect : pb::IMessage + public sealed partial class Protobuf_Tunnel_Disconnect : pb::IMessage #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE , pb::IBufferMessage #endif { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_C2S_Disconnect()); + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_Tunnel_Disconnect()); private pb::UnknownFieldSet _unknownFields; [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::AxibugProtobuf.ProtobufNoSugarReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Protobuf_Tunnel_Disconnect() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Protobuf_Tunnel_Disconnect(Protobuf_Tunnel_Disconnect other) : this() { + tunnelID_ = other.tunnelID_; + idx_ = other.idx_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public Protobuf_Tunnel_Disconnect Clone() { + return new Protobuf_Tunnel_Disconnect(this); + } + + /// Field number for the "TunnelID" field. + public const int TunnelIDFieldNumber = 1; + private uint tunnelID_; + /// + ///TunnelID + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint TunnelID { + get { return tunnelID_; } + set { + tunnelID_ = value; + } + } + + /// Field number for the "Idx" field. + public const int IdxFieldNumber = 2; + private uint idx_; + /// + ///单个隧道连接下标 + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public uint Idx { + get { return idx_; } + set { + idx_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as Protobuf_Tunnel_Disconnect); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(Protobuf_Tunnel_Disconnect other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (TunnelID != other.TunnelID) return false; + if (Idx != other.Idx) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (TunnelID != 0) hash ^= TunnelID.GetHashCode(); + if (Idx != 0) hash ^= Idx.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (TunnelID != 0) { + output.WriteRawTag(8); + output.WriteUInt32(TunnelID); + } + if (Idx != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Idx); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (TunnelID != 0) { + output.WriteRawTag(8); + output.WriteUInt32(TunnelID); + } + if (Idx != 0) { + output.WriteRawTag(16); + output.WriteUInt32(Idx); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (TunnelID != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TunnelID); + } + if (Idx != 0) { + size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Idx); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(Protobuf_Tunnel_Disconnect other) { + if (other == null) { + return; + } + if (other.TunnelID != 0) { + TunnelID = other.TunnelID; + } + if (other.Idx != 0) { + Idx = other.Idx; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + TunnelID = input.ReadUInt32(); + break; + } + case 16: { + Idx = input.ReadUInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + TunnelID = input.ReadUInt32(); + break; + } + case 16: { + Idx = input.ReadUInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Protobuf_Tunnel_DATA : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_Tunnel_DATA()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public static pbr::MessageDescriptor Descriptor { @@ -2098,442 +2162,14 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Disconnect() { + public Protobuf_Tunnel_DATA() { OnConstruction(); } partial void OnConstruction(); [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Disconnect(Protobuf_C2S_Disconnect other) : this() { - tunnelID_ = other.tunnelID_; - idx_ = other.idx_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_Disconnect Clone() { - return new Protobuf_C2S_Disconnect(this); - } - - /// Field number for the "TunnelID" field. - public const int TunnelIDFieldNumber = 1; - private uint tunnelID_; - /// - ///TunnelID - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint TunnelID { - get { return tunnelID_; } - set { - tunnelID_ = value; - } - } - - /// Field number for the "Idx" field. - public const int IdxFieldNumber = 2; - private uint idx_; - /// - ///单个隧道连接下标 - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint Idx { - get { return idx_; } - set { - idx_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Protobuf_C2S_Disconnect); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_C2S_Disconnect other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TunnelID != other.TunnelID) return false; - if (Idx != other.Idx) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (TunnelID != 0) hash ^= TunnelID.GetHashCode(); - if (Idx != 0) hash ^= Idx.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (TunnelID != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TunnelID); - } - if (Idx != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Idx); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_C2S_Disconnect other) { - if (other == null) { - return; - } - if (other.TunnelID != 0) { - TunnelID = other.TunnelID; - } - if (other.Idx != 0) { - Idx = other.Idx; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - } - #endif - - } - - public sealed partial class Protobuf_S2C_Disconnect : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_S2C_Disconnect()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::AxibugProtobuf.ProtobufNoSugarReflection.Descriptor.MessageTypes[9]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Disconnect() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Disconnect(Protobuf_S2C_Disconnect other) : this() { - tunnelID_ = other.tunnelID_; - idx_ = other.idx_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_Disconnect Clone() { - return new Protobuf_S2C_Disconnect(this); - } - - /// Field number for the "TunnelID" field. - public const int TunnelIDFieldNumber = 1; - private uint tunnelID_; - /// - ///TunnelID - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint TunnelID { - get { return tunnelID_; } - set { - tunnelID_ = value; - } - } - - /// Field number for the "Idx" field. - public const int IdxFieldNumber = 2; - private uint idx_; - /// - ///单个隧道连接下标 - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint Idx { - get { return idx_; } - set { - idx_ = value; - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Protobuf_S2C_Disconnect); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_S2C_Disconnect other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TunnelID != other.TunnelID) return false; - if (Idx != other.Idx) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (TunnelID != 0) hash ^= TunnelID.GetHashCode(); - if (Idx != 0) hash ^= Idx.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (TunnelID != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TunnelID); - } - if (Idx != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Idx); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_S2C_Disconnect other) { - if (other == null) { - return; - } - if (other.TunnelID != 0) { - TunnelID = other.TunnelID; - } - if (other.Idx != 0) { - Idx = other.Idx; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - } - } - } - #endif - - } - - public sealed partial class Protobuf_C2S_DATA : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_C2S_DATA()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::AxibugProtobuf.ProtobufNoSugarReflection.Descriptor.MessageTypes[10]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_DATA() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_DATA(Protobuf_C2S_DATA other) : this() { + public Protobuf_Tunnel_DATA(Protobuf_Tunnel_DATA other) : this() { tunnelID_ = other.tunnelID_; idx_ = other.idx_; hunterNetCoreData_ = other.hunterNetCoreData_; @@ -2541,8 +2177,8 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_C2S_DATA Clone() { - return new Protobuf_C2S_DATA(this); + public Protobuf_Tunnel_DATA Clone() { + return new Protobuf_Tunnel_DATA(this); } /// Field number for the "TunnelID" field. @@ -2586,11 +2222,11 @@ namespace AxibugProtobuf { [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { - return Equals(other as Protobuf_C2S_DATA); + return Equals(other as Protobuf_Tunnel_DATA); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_C2S_DATA other) { + public bool Equals(Protobuf_Tunnel_DATA other) { if (ReferenceEquals(other, null)) { return false; } @@ -2683,257 +2319,7 @@ namespace AxibugProtobuf { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_C2S_DATA other) { - if (other == null) { - return; - } - if (other.TunnelID != 0) { - TunnelID = other.TunnelID; - } - if (other.Idx != 0) { - Idx = other.Idx; - } - if (other.HunterNetCoreData.Length != 0) { - HunterNetCoreData = other.HunterNetCoreData; - } - _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(pb::CodedInputStream input) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - input.ReadRawMessage(this); - #else - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - case 26: { - HunterNetCoreData = input.ReadBytes(); - break; - } - } - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { - uint tag; - while ((tag = input.ReadTag()) != 0) { - switch(tag) { - default: - _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); - break; - case 8: { - TunnelID = input.ReadUInt32(); - break; - } - case 16: { - Idx = input.ReadUInt32(); - break; - } - case 26: { - HunterNetCoreData = input.ReadBytes(); - break; - } - } - } - } - #endif - - } - - public sealed partial class Protobuf_S2C_DATA : pb::IMessage - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - , pb::IBufferMessage - #endif - { - private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Protobuf_S2C_DATA()); - private pb::UnknownFieldSet _unknownFields; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pb::MessageParser Parser { get { return _parser; } } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public static pbr::MessageDescriptor Descriptor { - get { return global::AxibugProtobuf.ProtobufNoSugarReflection.Descriptor.MessageTypes[11]; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - pbr::MessageDescriptor pb::IMessage.Descriptor { - get { return Descriptor; } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_DATA() { - OnConstruction(); - } - - partial void OnConstruction(); - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_DATA(Protobuf_S2C_DATA other) : this() { - tunnelID_ = other.tunnelID_; - idx_ = other.idx_; - hunterNetCoreData_ = other.hunterNetCoreData_; - _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public Protobuf_S2C_DATA Clone() { - return new Protobuf_S2C_DATA(this); - } - - /// Field number for the "TunnelID" field. - public const int TunnelIDFieldNumber = 1; - private uint tunnelID_; - /// - ///TunnelID - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint TunnelID { - get { return tunnelID_; } - set { - tunnelID_ = value; - } - } - - /// Field number for the "Idx" field. - public const int IdxFieldNumber = 2; - private uint idx_; - /// - ///单个隧道连接下标 - /// - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public uint Idx { - get { return idx_; } - set { - idx_ = value; - } - } - - /// Field number for the "HunterNetCore_Data" field. - public const int HunterNetCoreDataFieldNumber = 3; - private pb::ByteString hunterNetCoreData_ = pb::ByteString.Empty; - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public pb::ByteString HunterNetCoreData { - get { return hunterNetCoreData_; } - set { - hunterNetCoreData_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); - } - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override bool Equals(object other) { - return Equals(other as Protobuf_S2C_DATA); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public bool Equals(Protobuf_S2C_DATA other) { - if (ReferenceEquals(other, null)) { - return false; - } - if (ReferenceEquals(other, this)) { - return true; - } - if (TunnelID != other.TunnelID) return false; - if (Idx != other.Idx) return false; - if (HunterNetCoreData != other.HunterNetCoreData) return false; - return Equals(_unknownFields, other._unknownFields); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override int GetHashCode() { - int hash = 1; - if (TunnelID != 0) hash ^= TunnelID.GetHashCode(); - if (Idx != 0) hash ^= Idx.GetHashCode(); - if (HunterNetCoreData.Length != 0) hash ^= HunterNetCoreData.GetHashCode(); - if (_unknownFields != null) { - hash ^= _unknownFields.GetHashCode(); - } - return hash; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public override string ToString() { - return pb::JsonFormatter.ToDiagnosticString(this); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void WriteTo(pb::CodedOutputStream output) { - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - output.WriteRawMessage(this); - #else - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (HunterNetCoreData.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(HunterNetCoreData); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(output); - } - #endif - } - - #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { - if (TunnelID != 0) { - output.WriteRawTag(8); - output.WriteUInt32(TunnelID); - } - if (Idx != 0) { - output.WriteRawTag(16); - output.WriteUInt32(Idx); - } - if (HunterNetCoreData.Length != 0) { - output.WriteRawTag(26); - output.WriteBytes(HunterNetCoreData); - } - if (_unknownFields != null) { - _unknownFields.WriteTo(ref output); - } - } - #endif - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public int CalculateSize() { - int size = 0; - if (TunnelID != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(TunnelID); - } - if (Idx != 0) { - size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Idx); - } - if (HunterNetCoreData.Length != 0) { - size += 1 + pb::CodedOutputStream.ComputeBytesSize(HunterNetCoreData); - } - if (_unknownFields != null) { - size += _unknownFields.CalculateSize(); - } - return size; - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute] - public void MergeFrom(Protobuf_S2C_DATA other) { + public void MergeFrom(Protobuf_Tunnel_DATA other) { if (other == null) { return; } diff --git a/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml b/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..9b45bd1 --- /dev/null +++ b/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,14 @@ + + + + + Release + Any CPU + F:\Sin365\NoSugarNet\Lib\NetLib_Standard2 + FileSystem + <_TargetId>Folder + netstandard2.0 + + \ No newline at end of file diff --git a/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml.user b/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 0000000..57720b4 --- /dev/null +++ b/NoSugarNet.DataHelper/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,10 @@ + + + + + True|2024-04-15T06:43:38.1978223Z;True|2024-04-15T14:42:22.9030158+08:00;True|2024-04-15T14:10:55.2191388+08:00;True|2024-04-15T14:07:27.2723988+08:00;False|2024-04-15T14:07:03.8682886+08:00;False|2024-04-15T14:06:57.0680795+08:00; + + + \ No newline at end of file diff --git a/NoSugarNet.sln b/NoSugarNet.sln index e11546d..4125f73 100644 --- a/NoSugarNet.sln +++ b/NoSugarNet.sln @@ -22,7 +22,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoSugarNet.ServerCli", "Sam EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NetLib_Standard2", "NetLib_Standard2", "{4A660CAE-CD92-411C-9D8E-7CB677DB3C74}" ProjectSection(SolutionItems) = preProject - Lib\NetLib_Standard2\HaoYueNet.ClientNetworkNet.Standard2.dll = Lib\NetLib_Standard2\HaoYueNet.ClientNetworkNet.Standard2.dll + Lib\NetLib_Standard2\HaoYueNet.ClientNetwork.Standard2.dll = Lib\NetLib_Standard2\HaoYueNet.ClientNetwork.Standard2.dll Lib\NetLib_Standard2\HaoYueNet.ServerNetwork.Standard2.dll = Lib\NetLib_Standard2\HaoYueNet.ServerNetwork.Standard2.dll Lib\NetLib_Standard2\NoSugarNet.DataHelper.deps.json = Lib\NetLib_Standard2\NoSugarNet.DataHelper.deps.json Lib\NetLib_Standard2\NoSugarNet.DataHelper.dll = Lib\NetLib_Standard2\NoSugarNet.DataHelper.dll @@ -31,7 +31,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NetLib_Standard2", "NetLib_ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoSugarNet.ClientCore.Standard2", "NoSugarNet.ClientCore.Standard2\NoSugarNet.ClientCore.Standard2.csproj", "{5DB2B608-6F99-430A-99AC-534410393955}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoSugarNet.Adapter", "NoSugarNet.Adapter\NoSugarNet.Adapter.csproj", "{961FA85B-B6A7-4F45-8239-9E91315253B4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NoSugarNet.Adapter", "NoSugarNet.Adapter\NoSugarNet.Adapter.csproj", "{961FA85B-B6A7-4F45-8239-9E91315253B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoSugarNet.ClientCli.Standard2", "NoSugarNet.ClientCli.Standard2\NoSugarNet.ClientCli.Standard2.csproj", "{97906C2A-2C93-4C63-A237-A75B6EDA8FA4}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -63,6 +65,10 @@ Global {961FA85B-B6A7-4F45-8239-9E91315253B4}.Debug|Any CPU.Build.0 = Debug|Any CPU {961FA85B-B6A7-4F45-8239-9E91315253B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {961FA85B-B6A7-4F45-8239-9E91315253B4}.Release|Any CPU.Build.0 = Release|Any CPU + {97906C2A-2C93-4C63-A237-A75B6EDA8FA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {97906C2A-2C93-4C63-A237-A75B6EDA8FA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {97906C2A-2C93-4C63-A237-A75B6EDA8FA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {97906C2A-2C93-4C63-A237-A75B6EDA8FA4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -71,6 +77,7 @@ Global {29D76CF3-BF7E-45A5-9957-2CBC0A41B6FB} = {5E65F25A-8B59-4FC7-8582-C6887C3CD0A1} {65220036-9A81-49FA-A5BC-DA06783D2E52} = {5E65F25A-8B59-4FC7-8582-C6887C3CD0A1} {4A660CAE-CD92-411C-9D8E-7CB677DB3C74} = {EDA9D3FD-1A72-434D-81F6-B1B420406D20} + {97906C2A-2C93-4C63-A237-A75B6EDA8FA4} = {5E65F25A-8B59-4FC7-8582-C6887C3CD0A1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {637DC2BB-F9BB-41A2-ADC0-B41B871F66DE} diff --git a/NosugarNetForUnity/Assets/MainUI.cs b/NosugarNetForUnity/Assets/MainUI.cs index d539806..35ff20f 100644 --- a/NosugarNetForUnity/Assets/MainUI.cs +++ b/NosugarNetForUnity/Assets/MainUI.cs @@ -1,7 +1,6 @@ -using NoSugarNet.ClientCoreNet.Standard2; +using NoSugarNet.ClientCore; +using NoSugarNet.ClientCore.Common; using System; -using System.Collections; -using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; @@ -28,8 +27,7 @@ public class MainUI : MonoBehaviour btnStop.onClick.AddListener(StopNoSugarNetClient); AddLog(""); - AppNoSugarNet.OnUpdateStatus += OnUpdateStatus; - AppNoSugarNet.Init(OnNoSugarNetLog); + AppNoSugarNet.Init(new System.Collections.Generic.Dictionary(),0, OnNoSugarNetLog); } private void OnDisable() diff --git a/NosugarNetForUnity/Assets/Plugins/HaoYueNet.ClientNetwork.Standard2.dll b/NosugarNetForUnity/Assets/Plugins/HaoYueNet.ClientNetwork.Standard2.dll new file mode 100644 index 0000000000000000000000000000000000000000..3802b84e5e2727cdf790b9e869fb721577dfbabb GIT binary patch literal 34304 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 literal 59904 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≀{kI2x>!F3Yi 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 diff --git a/Sample/NoSugarNet.ServerCli/NoSugarNet.ServerCli.csproj b/Sample/NoSugarNet.ServerCli/NoSugarNet.ServerCli.csproj index c941ed4..c533bbd 100644 --- a/Sample/NoSugarNet.ServerCli/NoSugarNet.ServerCli.csproj +++ b/Sample/NoSugarNet.ServerCli/NoSugarNet.ServerCli.csproj @@ -16,6 +16,7 @@ +