342 lines
13 KiB
C#
342 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using SF_Demo.Tools;
|
|
|
|
namespace Go_Frp
|
|
{
|
|
public partial class Go_Frp : Form
|
|
{
|
|
// 添加字典用于存储 frpc 进程
|
|
private Dictionary<string, Process> frpcProcesses = new Dictionary<string, Process>();
|
|
JobManager jobManager = JobManager.Instance;
|
|
|
|
public Go_Frp()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
// Frp 类
|
|
public class Frp
|
|
{
|
|
public string host { get; set; }
|
|
public string port { get; set; }
|
|
public string token { get; set; }
|
|
}
|
|
|
|
|
|
// 确保窗口只触发一次
|
|
private bool isLoginShow = false;
|
|
|
|
// 定时器字段
|
|
private System.Windows.Forms.Timer statusCheckTimer;
|
|
|
|
// 地址信息
|
|
private string url = "http://192.168.177.1:8080/servers";
|
|
|
|
// 窗口启动时执行
|
|
protected override async void OnLoad(EventArgs e)
|
|
{
|
|
base.OnLoad(e);
|
|
|
|
// 登录窗口
|
|
if (!isLoginShow)
|
|
{
|
|
isLoginShow = true;
|
|
|
|
// 创建并显示窗口
|
|
using (Login login = new Login())
|
|
{
|
|
login.ShowDialog();
|
|
}
|
|
}
|
|
|
|
// 服务器状态
|
|
// 立即执行一次
|
|
await CheckServerStatusAsync();
|
|
|
|
// 初始化定时
|
|
statusCheckTimer = new System.Windows.Forms.Timer();
|
|
statusCheckTimer.Interval = 5000;
|
|
statusCheckTimer.Tick += async (sendier, args) => await CheckServerStatusAsync();
|
|
}
|
|
|
|
// 连接按钮
|
|
private async void Connect_but_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// 获取数据
|
|
var data = await FetchFrpDataAsync(url);
|
|
|
|
// 程序路径
|
|
string appPath = "../../Frpc/frpc.exe";
|
|
|
|
// 日志目录
|
|
string logDirPath = "../../Frpc/log";
|
|
|
|
// 检查并创建日志目录
|
|
if (!Directory.Exists(logDirPath))
|
|
{
|
|
Directory.CreateDirectory(logDirPath);
|
|
}
|
|
|
|
// 服务器信息
|
|
string local_host = Host_box.Text;
|
|
string local_port = Port_box.Text;
|
|
string local_domain = Domain_box.Text;
|
|
|
|
// 进程启动
|
|
foreach (var server in data)
|
|
{
|
|
try
|
|
{
|
|
// 创建日志文件
|
|
string logFile = Path.Combine(logDirPath, $"{server.Key}.log");
|
|
|
|
// 启动参数
|
|
string arguments = $"http " +
|
|
$"-s {server.Value.host} " +
|
|
$"-P {server.Value.port} " +
|
|
$"-t {server.Value.token} " +
|
|
$"-i {local_host} " +
|
|
$"-l {local_port} " +
|
|
$"-d \"{local_domain}\" " +
|
|
$"-n {server.Key}";
|
|
|
|
// 记录启动命令到日志中
|
|
File.AppendAllText(logFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 启动命令: ./frpc.exe {arguments}\n");
|
|
|
|
// 创建启动
|
|
ProcessStartInfo startinfo = new ProcessStartInfo
|
|
{
|
|
FileName = appPath,
|
|
//FileName = "cmd.exe",
|
|
Arguments = arguments,
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true,
|
|
|
|
};
|
|
|
|
// 创建并启动进程
|
|
Process frpcProcess = new Process
|
|
{
|
|
StartInfo = startinfo,
|
|
EnableRaisingEvents = true
|
|
};
|
|
|
|
// 设置输出事件处理
|
|
frpcProcess.OutputDataReceived += (s, args) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(args.Data))
|
|
{
|
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
string cleanData = RemoveAnsiEscapeCodes(args.Data);
|
|
string logMessage = $"[{timestamp}] {cleanData}";
|
|
|
|
try
|
|
{
|
|
// 写入日志文件
|
|
File.AppendAllText(logFile, logMessage + Environment.NewLine);
|
|
|
|
// 更新显示
|
|
this.Invoke((MethodInvoker)delegate
|
|
{
|
|
if (server.Key == "Frp1")
|
|
{
|
|
Server_Log1.AppendText(logMessage + Environment.NewLine);
|
|
Server_Log1.SelectionStart = Server_Log1.Text.Length;
|
|
Server_Log1.ScrollToCaret();
|
|
}
|
|
else if (server.Key == "Frp2")
|
|
{
|
|
Server_Log2.AppendText(logMessage + Environment.NewLine);
|
|
Server_Log2.SelectionStart = Server_Log2.Text.Length;
|
|
Server_Log2.ScrollToCaret();
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"处理输出时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
};
|
|
|
|
// 错误输出处理
|
|
frpcProcess.ErrorDataReceived += (s, args) =>
|
|
{
|
|
if (!string.IsNullOrEmpty(args.Data))
|
|
{
|
|
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
string cleanData = RemoveAnsiEscapeCodes(args.Data);
|
|
string logMessage = $"[{timestamp}] ERROR: {cleanData}";
|
|
|
|
try
|
|
{
|
|
File.AppendAllText(logFile, logMessage + Environment.NewLine);
|
|
|
|
this.Invoke((MethodInvoker)delegate
|
|
{
|
|
if (server.Key == "Frp1")
|
|
{
|
|
Server_Log1.AppendText(logMessage + Environment.NewLine);
|
|
Server_Log1.SelectionStart = Server_Log1.Text.Length;
|
|
Server_Log1.ScrollToCaret();
|
|
}
|
|
else if (server.Key == "Frp2")
|
|
{
|
|
Server_Log2.AppendText(logMessage + Environment.NewLine);
|
|
Server_Log2.SelectionStart = Server_Log2.Text.Length;
|
|
Server_Log2.ScrollToCaret();
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"处理错误输出时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
};
|
|
|
|
// 启动进程
|
|
if (!frpcProcess.Start())
|
|
{
|
|
throw new Exception("进程启动失败");
|
|
}
|
|
|
|
// 添加到作业管理器
|
|
jobManager.AddProcessToJob(frpcProcess);
|
|
|
|
// 开始异步读取
|
|
frpcProcess.BeginOutputReadLine();
|
|
frpcProcess.BeginErrorReadLine();
|
|
|
|
// 存储进程引用
|
|
frpcProcesses[server.Key] = frpcProcess;
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"启动 {server.Key} 失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"连接失败: {ex.Message}\n{ex.StackTrace}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
// 获取数据
|
|
private async Task<Dictionary<string, Frp>> FetchFrpDataAsync(string url)
|
|
{
|
|
using (HttpClient client = new HttpClient())
|
|
{
|
|
HttpResponseMessage response = await client.GetAsync(url);
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
string jsonResponse = await response.Content.ReadAsStringAsync();
|
|
|
|
// 动态反序列化 JSON 数据
|
|
return JsonSerializer.Deserialize<Dictionary<string, Frp>>(jsonResponse);
|
|
}
|
|
}
|
|
|
|
// 检查服务器状态
|
|
private async Task CheckServerStatusAsync()
|
|
{
|
|
var data = await FetchFrpDataAsync(url);
|
|
// 修改服务器状态
|
|
foreach (var server in data)
|
|
{
|
|
string ip = server.Value.host;
|
|
string port = server.Value.port;
|
|
|
|
bool isConnected = await CheckServerConnectionAsync(ip, port);
|
|
|
|
if (server.Key == "Frp1")
|
|
{
|
|
if (isConnected)
|
|
{
|
|
Server_connect1.Text = "在线";
|
|
Server_connect1.ForeColor = Color.Lime;
|
|
}
|
|
else
|
|
{
|
|
Server_connect1.Text = "离线";
|
|
Server_connect1.ForeColor = Color.Red;
|
|
}
|
|
}
|
|
else if (server.Key == "Frp2")
|
|
{
|
|
if (isConnected)
|
|
{
|
|
Server_connect2.Text = "在线";
|
|
Server_connect2.ForeColor = Color.Lime;
|
|
}
|
|
else
|
|
{
|
|
Server_connect2.Text = "离线";
|
|
Server_connect2.ForeColor = Color.Red;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 检查服务器连接
|
|
private async Task<bool> CheckServerConnectionAsync(string ip, string port)
|
|
{
|
|
try
|
|
{
|
|
if (!int.TryParse(port, out int portNumber) || portNumber < 1 || portNumber > 65535)
|
|
{
|
|
// 如果端口无效(非数字或超出有效范围),返回 false
|
|
return false;
|
|
}
|
|
|
|
using (TcpClient tcpClient = new TcpClient())
|
|
{
|
|
// 尝试连接服务器
|
|
var connectTask = tcpClient.ConnectAsync(ip, portNumber);
|
|
var timeoutTask = Task.Delay(3000); // 设置超时时间
|
|
if (await Task.WhenAny(connectTask, timeoutTask) == connectTask)
|
|
{
|
|
return tcpClient.Connected;
|
|
}
|
|
else
|
|
{
|
|
return false; // 超时未连接
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// 去除 ANSI 转义序列函数
|
|
private string RemoveAnsiEscapeCodes(string input)
|
|
{
|
|
// 正则表达式匹配 ANSI 转义序列
|
|
string pattern = @"\x1b\[[0-9;]*[a-zA-Z]";
|
|
return Regex.Replace(input, pattern, string.Empty);
|
|
}
|
|
}
|
|
}
|