You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#if NETCORE
using System; using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Builder; using System.Threading.Tasks; using System.Net; using System.Net.WebSockets; using System.Security.Cryptography.X509Certificates;
namespace Apewer.Web {
/// <summary>ASP.NET Core 服务器。</summary>
public sealed class AspNetCore {
#region servers
static AspNetCore[] _servers = new AspNetCore[65536];
internal static AspNetCore Get(int port) => _servers[port];
static object _operation = new object();
static string Add(AspNetCore server) { if (server == null) return null; var port = server.Port; lock (_operation) { if (_servers[port] != null) return "端口已配置。"; _servers[port] = server; } return null; }
static void Stop(int port) { var server = null as AspNetCore; lock (_operation) { server = _servers[port]; } if (server != null) { var host = server._host; Stop(host); } }
static void Stop(IDisposable disposable) => RuntimeUtility.Dispose(disposable);
/// <summary>获取所有正在解析的端口。</summary>
public static int[] Ports { get { var count = 0; var arr1 = new int[65536]; for (var i = 0; i < _servers.Length; i++) { var server = _servers[i]; if (server == null) continue; arr1[count] = i; count += 1; } var arr2 = new int[count]; if (count > 0) Array.Copy(arr1, 0, arr2, 0, count); return arr2; } }
#endregion
#region base
private IHostBuilder _builder = null; private IHost _host = null; private int _port = 0; private bool _locked = false;
/// <summary>监听的端口。默认值:0,自动选择 80 端口或 443 端口。</summary>
public int Port { get { return _port > 0 ? _port : (Certificate == null ? 80 : 443); } set { _port = value; } }
/// <summary>获取或设置将要使用的证书。</summary>
public X509Certificate2 Certificate { get; set; }
/// <summary>获取或设置请求的最大 Body 大小,单位为字节。可接受的最小值为 1048576 字节(1 MB)。默认值:1073741824。</summary>
public long MaxBody { get; set; } = 1073741824L;
/// <summary>获取或设置 Context 处理程序。</summary>
public Action<HttpContext> Context { get; set; }
/// <summary>获取或设置 WebSocket 处理程序。</summary>
public Action<HttpContext, System.Net.WebSockets.WebSocket> WebSocket { get; set; }
private string Run<TStartup>(Action<IWebHostBuilder> configure, bool async = false) where TStartup : class { if (Context == null) return "未指定 Context 处理程序。";
var port = Port; if (port < ushort.MinValue || port > ushort.MaxValue) return "端口无法使用。"; if (NetworkUtility.ListActiveTcpPort().Contains(port)) return "端口无法使用。";
try { _builder = Host.CreateDefaultBuilder().ConfigureWebHostDefaults((builder) => { configure?.Invoke(builder); builder.UseStartup<TStartup>(); }); _host = _builder.Build();
// 添加到 Servers。
var add = Add(this); if (!string.IsNullOrEmpty(add)) { return add; Stop(_host); }
// 异步运行。
if (async) { _host.RunAsync(); return null; }
// 同步运行。
_host.Run(); } catch (Exception ex) { return ex.Message; } if (!async) Stop(port);
return null; }
#endregion
/// <summary>启动 Kestrel 服务器。</summary>
public string RunKestrel(bool async = false) => Run<KestrelStartup>((builder) => builder.ConfigureKestrel((options) => { // 配置端口和证书。
options.Listen(IPAddress.Any, Port, (listen) => { if (Certificate != null) listen.UseHttps(Certificate); });
// 同步 IO。
options.AllowSynchronousIO = ApiOptions.AllowSynchronousIO;
// 限制请求大小,最小为 1MB,默认为 1GB。
options.Limits.MaxRequestBodySize = (MaxBody < 1048576L) ? 1073741824L : MaxBody; }), async);
/// <summary>启动基于 HTTP.sys 的服务器。</summary>
/// <remarks>
/// <para>HTTP.sys 是仅在 Windows 上运行的适用于 ASP.NET Core 的 Web 服务器。<br />HTTP.sys 是 Kestrel 服务器的替代选择,提供了一些 Kestrel 不提供的功能。</para>
/// <para>HTTP.sys 支持以下功能:<br />Windows 身份验证;<br />端口共享;<br />具有 SNI 的 HTTPS;<br />基于 TLS 的 HTTP/2(Windows 10 或更高版本);<br />直接文件传输;<br />响应缓存;<br />WebSocket(Windows 8 或更高版本)。</para>
/// </remarks>
public string RunHttpSys(string ip, bool async = false) { // 检查 IP 地址格式。
if (!NetworkUtility.IsIP(ip)) return "IP 地址格式无效。";
return Run<HttpSysStartup>((builder) => builder.UseHttpSys((options) => { // 配置端口和证书。
var protocol = Certificate == null ? "http" : "https"; var url = $"{protocol}://{ip}:{Port}"; options.UrlPrefixes.Add(url);
// 同步 IO。
options.AllowSynchronousIO = ApiOptions.AllowSynchronousIO;
// 限制请求大小,最小为 1MB,默认为 1GB。
options.MaxRequestBodySize = (MaxBody < 1048576L) ? 1073741824L : MaxBody;
// 认证。
options.Authentication.Schemes = Microsoft.AspNetCore.Server.HttpSys.AuthenticationSchemes.None; options.Authentication.AllowAnonymous = true; }), async); }
}
}
#endif
|