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");
+ }
}
///