Files
downkyicore/DownKyi.Core/Aria2cNet/Server/AriaServer.cs
2024-12-02 13:46:03 +08:00

272 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Diagnostics;
using System.Text;
using DownKyi.Core.Aria2cNet.Client;
using DownKyi.Core.Logging;
using DownKyi.Core.Storage;
using Console = DownKyi.Core.Utils.Debugging.Console;
namespace DownKyi.Core.Aria2cNet.Server
{
public static class AriaServer
{
public static int ListenPort; // 服务器端口
private static Process Server;
/// <summary>
/// 启动aria2c服务器
/// </summary>
/// <param name="config"></param>
/// <param name="action"></param>
/// <returns></returns>
public static async Task<bool> StartServerAsync(AriaConfig config, Action<string> action)
{
// aria端口
ListenPort = config.ListenPort;
// aria目录
// var ariaDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "aria");
var ariaDir = StorageManager.GetAriaDir();
// 会话文件
#if DEBUG
var sessionFile = Path.Combine(ariaDir, "aira.session");
#else
var sessionFile = Path.Combine(ariaDir, "aira.session.gz");
#endif
// 日志文件
var logFile = Path.Combine(ariaDir, "aira.log");
// 自动保存会话文件的时间间隔
var saveSessionInterval = 30;
// --enable-rpc --rpc-listen-all=true --rpc-allow-origin-all=true --continue=true
await Task.Run(() =>
{
// 创建目录和文件
if (!Directory.Exists(ariaDir))
{
Directory.CreateDirectory(ariaDir);
}
if (!File.Exists(sessionFile))
{
var stream = File.Create(sessionFile);
stream.Close();
}
if (!File.Exists(logFile))
{
var stream = File.Create(logFile);
stream.Close();
}
else
{
// 日志文件存在如果大于100M则删除
try
{
var stream = File.Open(logFile, FileMode.Open);
if (stream.Length >= 10 * 1024 * 1024L)
{
stream.SetLength(0);
}
stream.Close();
}
catch (Exception e)
{
Console.PrintLine("StartServerAsync()发生其他异常: {0}", e);
LogManager.Error("AriaServer", e);
}
}
// header 解析
var headers = string.Empty;
if (config.Headers != null)
{
headers = config.Headers.Aggregate(headers,
(current, header) => current + $"--header=\"{header}\" ");
}
var executeName = "aria2c";
if (OperatingSystem.IsWindows())
{
executeName += ".exe";
}
ExecuteProcess($"aria2/{executeName}",
$"--enable-rpc --rpc-listen-all=true --rpc-allow-origin-all=true " +
$"--check-certificate=false " + // 解决问题 SSL/TLS handshake failure
$"--rpc-listen-port={config.ListenPort} " +
$"--rpc-secret={config.Token} " +
$"--input-file=\"{sessionFile}\" --save-session=\"{sessionFile}\" " +
$"--save-session-interval={saveSessionInterval} " +
$"--log=\"{logFile}\" --log-level={config.LogLevel.ToString("G").ToLower()} " + // log-level: 'debug' 'info' 'notice' 'warn' 'error'
$"--max-concurrent-downloads={config.MaxConcurrentDownloads} " + // 最大同时下载数(任务数)
$"--max-connection-per-server={config.MaxConnectionPerServer} " + // 同服务器连接数
$"--split={config.Split} " + // 单文件最大线程数
//$"--max-tries={config.MaxTries} retry-wait=3 " + // 尝试重连次数
$"--min-split-size={config.MinSplitSize}M " + // 最小文件分片大小, 下载线程数上限取决于能分出多少片, 对于小文件重要
$"--max-overall-download-limit={config.MaxOverallDownloadLimit} " + // 下载速度限制
$"--max-download-limit={config.MaxDownloadLimit} " + // 下载单文件速度限制
$"--continue={config.ContinueDownload.ToString().ToLower()} " + // 断点续传
$"--allow-overwrite=true " + // 允许复写文件
$"--auto-file-renaming=false " +
$"--file-allocation={config.FileAllocation.ToString("G").ToLower()} " + // 文件预分配, none prealloc
$"{headers}" + // header
"",
null, (s, e) =>
{
if (string.IsNullOrEmpty(e.Data) || e.Data.Replace(" ", "") == "")
{
return;
}
Console.PrintLine(e.Data);
LogManager.Debug("AriaServer", e.Data);
action.Invoke(e.Data);
});
});
return true;
}
/// <summary>
/// 关闭aria2c服务器异步方法
/// </summary>
/// <returns></returns>
public static async Task<bool> CloseServerAsync()
{
await AriaClient.ShutdownAsync();
// 等待进程结束
await Task.Run(() =>
{
Server.WaitForExit(30000);
try
{
Server.Kill();
}
catch (Exception)
{
}
});
return true;
}
/// <summary>
/// 强制关闭aria2c服务器异步方法
/// </summary>
/// <returns></returns>
public static async Task<bool> ForceCloseServerAsync()
{
//await Task.Run(() =>
//{
// if (Server == null) { return; }
// Server.Kill();
// Server = null; // 将Server指向null
//});
//return true;
await AriaClient.ForceShutdownAsync();
return true;
}
/// <summary>
/// 关闭aria2c服务器
/// </summary>
/// <returns></returns>
public static bool CloseServer()
{
var task = AriaClient.ShutdownAsync();
if (task.Result != null && task.Result.Result != null && task.Result.Result == "OK")
{
// 等待进程结束
Server.WaitForExit(30000);
try
{
Server.Kill();
}
catch (Exception)
{
}
return true;
}
return false;
}
/// <summary>
/// 强制关闭aria2c服务器
/// </summary>
/// <returns></returns>
public static bool ForceCloseServer()
{
var task = AriaClient.ForceShutdownAsync();
if (task.Result != null && task.Result.Result != null && task.Result.Result == "OK")
{
return true;
}
return false;
}
/// <summary>
/// 杀死Aria进程
/// </summary>
/// <param name="processName"></param>
/// <returns></returns>
public static bool KillServer(string processName = "aria2c")
{
Process[] processes = Process.GetProcessesByName(processName);
foreach (var process in processes)
{
try
{
process.Kill();
}
catch (Exception e)
{
Console.PrintLine("KillServer()发生异常: {0}", e);
LogManager.Error("AriaServer", e);
}
}
return true;
}
private static void ExecuteProcess(string exe, string arg, string? workingDirectory,
DataReceivedEventHandler output)
{
var p = new Process();
Server = p;
p.StartInfo.FileName = exe;
p.StartInfo.Arguments = arg;
// 工作目录
if (workingDirectory != null)
{
p.StartInfo.WorkingDirectory = workingDirectory;
}
// 输出信息重定向
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
// 将 StandardErrorEncoding 改为 UTF-8 才不会出现中文乱码
p.StartInfo.StandardOutputEncoding = Encoding.UTF8;
p.StartInfo.StandardErrorEncoding = Encoding.UTF8;
p.OutputDataReceived += output;
p.ErrorDataReceived += output;
// 启动线程
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
}
}
}