diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 30cc6523..57a6c24b 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -51,6 +51,7 @@ namespace Netch.Forms private void MainForm_Load(object sender, EventArgs e) { + OnlyInstance.Called += OnCalled; // 计算 ComboBox绘制 目标宽度 _eWidth = ServerComboBox.Width / 10; @@ -107,6 +108,21 @@ namespace Netch.Forms }); } + private void OnCalled(object sender, OnlyInstance.Commands e) + { + switch (e) + { + case OnlyInstance.Commands.Show: + NotifyIcon_MouseDoubleClick(null, null); + break; + case OnlyInstance.Commands.Exit: + Exit(true); + break; + default: + throw new ArgumentOutOfRangeException(nameof(e), e, null); + } + } + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { diff --git a/Netch/Models/Setting.cs b/Netch/Models/Setting.cs index f312ce40..89958ffe 100644 --- a/Netch/Models/Setting.cs +++ b/Netch/Models/Setting.cs @@ -124,6 +124,11 @@ namespace Netch.Models /// public int RedirectorTCPPort = 3901; + /// + /// UDP Socket 占用端口 + /// + public int UDPSocketPort = 18291; + /// /// HTTP 和 Socks5 本地代理地址 /// diff --git a/Netch/Netch.cs b/Netch/Netch.cs index d4adc0fd..db7f4546 100644 --- a/Netch/Netch.cs +++ b/Netch/Netch.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using Netch.Controllers; using Netch.Forms; @@ -65,13 +66,14 @@ namespace Netch // 检查是否已经运行 if (!mutex.WaitOne(0, false)) { - // 弹出提示 - MessageBoxX.Show(i18N.Translate("Netch is already running")); + OnlyInstance.Send(OnlyInstance.Commands.Show); // 退出进程 Environment.Exit(1); } + Task.Run(OnlyInstance.Server); + // 绑定错误捕获 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); Application.ThreadException += Application_OnException; diff --git a/Netch/Utils/OnlyInstance.cs b/Netch/Utils/OnlyInstance.cs new file mode 100644 index 00000000..bbaf4843 --- /dev/null +++ b/Netch/Utils/OnlyInstance.cs @@ -0,0 +1,71 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace Netch.Utils +{ + public class OnlyInstance + { + public enum Commands + { + Show, + Exit + } + + public static event EventHandler Called; + + private static void OnCalled(Commands e) + { + Called?.Invoke(null, e); + } + + public static async void Server() + { + try + { + if (PortHelper.PortInUse(Global.Settings.UDPSocketPort)) + { + Global.Settings.UDPSocketPort = PortHelper.GetAvailablePort(); + Configuration.Save(); + } + + var data = new byte[1024]; + var newsock = new UdpClient(new IPEndPoint(IPAddress.Loopback, Global.Settings.UDPSocketPort)); + + while (true) + { + var result = await newsock.ReceiveAsync(); + data = result.Buffer; + if (Enum.TryParse(Encoding.ASCII.GetString(data, 0, data.Length), out var command)) + { + OnCalled(command); + } + } + } + catch (Exception e) + { + Logging.Error(e.ToString()); + } + } + + public static async void Send(Commands command) + { + try + { + using (var udpClient = new UdpClient(Global.Settings.UDPSocketPort)) + { + udpClient.Connect(IPAddress.Loopback, Global.Settings.UDPSocketPort); + var sendBytes = Encoding.ASCII.GetBytes(command.ToString()); + await udpClient.SendAsync(sendBytes, sendBytes.Length); + + udpClient.Close(); + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } + } + } +} \ No newline at end of file diff --git a/Netch/Utils/PortHelper.cs b/Netch/Utils/PortHelper.cs index f787b2fd..b480c6c1 100644 --- a/Netch/Utils/PortHelper.cs +++ b/Netch/Utils/PortHelper.cs @@ -111,6 +111,20 @@ namespace Netch.Utils return isPortExcluded && (isTcpUsed || isUdpUsed); } + + public static int GetAvailablePort() + { + for (var i = 0; i < 55535; i++) + { + var p = new Random().Next(10000, 65535); + if (!PortInUse(p)) + { + return p; + } + } + + throw new Exception("Cant Generate Available Port"); + } } ///