在 .NET Core worker 项目中使用 Kestrel

use Kestrel in .NET Core worker project

我使用 Visual Studio 提供的模板创建了一个新的 .NET Core worker 项目。我想监听传入的 TCP 消息和 HTTP 请求。我正在关注 David Fowler's "Multi-protocol Server with ASP.NET Core and Kestrel" repository 如何设置 Kestrel。

AFAIK 我所要做的就是安装 Microsoft.AspNetCore.Hosting 包以访问 UseKestrel 方法。

Program.cs 文件中我正在这样做

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}

不幸的是,我无法将 UseKestrel 附加到 ConfigureServices 方法。我认为这是因为我正在使用 IHostBuilder 接口而不是 IWebHostBuilder 接口。

此项目不应是 Web API 项目,它应保留为 Worker 项目。

知道如何为此配置 Kestrel 吗?


我尝试将代码更改为示例存储库中的代码

using System.Net;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;

namespace Service
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .ConfigureServices(services =>
                {
                    // ...
                })
                .UseKestrel(options =>
                {
                    // ...
                });
    }
}

这样做仍然无法解决 WebHost 并出现这些错误

我认为发生这种情况是因为工作项目没有使用 Web SDK。

您使用 IHostbuilder 启用 HTTP 工作负载,您需要在 Host.CreateDefaultBuilder 中添加 .ConfigureWebHostDefaults。由于 Kestrel 是网络服务器,您只能从网络主机配置它。

在您的 program.cs 文件中

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                   webBuilder.UseStartup<Startup>();
                    webBuilder.UseKestrel(options =>
                    {
                        // TCP 8007
                        options.ListenLocalhost(8007, builder =>
                        {
                            builder.UseConnectionHandler<MyEchoConnectionHandler>();
                        });

                        // HTTP 5000
                        options.ListenLocalhost(5000);

                        // HTTPS 5001
                        options.ListenLocalhost(5001, builder =>
                        {
                            builder.UseHttps();
                        });
                    });
                });

public static IHostBuilder CreateHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseKestrel(options =>
            {
                // TCP 8007
                options.ListenLocalhost(8007, builder =>
                {
                    builder.UseConnectionHandler<MyEchoConnectionHandler>();
                });

                // HTTP 5000
                options.ListenLocalhost(5000);

                // HTTPS 5001
                options.ListenLocalhost(5001, builder =>
                {
                    builder.UseHttps();
                });
            });

由于您使用网络服务器启用 HTTP 工作负载,因此您的项目必须是 web 类型。只有当项目是 web 类型时才会启用 WebHost。所以您需要更改您的 SDK 以在您的 csproj 文件中使用 web。

<Project Sdk="Microsoft.NET.Sdk.Web">

参考:

NET 5.0 如下

  1. 添加对 ASP.NET 的框架引用:

    <Project Sdk="Microsoft.NET.Sdk.Worker">
        <ItemGroup>
            <FrameworkReference Include="Microsoft.AspNetCore.App" />
        </ItemGroup>
    </Project>
    
  2. program.cs

    上添加网页配置
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
                config.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true);
    
                Configuration = config.Build();
             })
    
             //Worker
             .ConfigureServices((hostContext, services) =>
             {
                 services.AddHostedService<ServiceDemo>();
             })
    
             // web site
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
                 webBuilder.UseKestrel(options =>
                 {
                     // HTTP 5000
                     options.ListenLocalhost(58370);
    
                     // HTTPS 5001
                     options.ListenLocalhost(44360, builder =>
                     {
                         builder.UseHttps();
                     });
                 });
             });
    
  3. 配置Startup

    public class Startup
    {
        public IConfiguration Configuration { get; }
    
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
        }
    
        public void Configure(IApplicationBuilder app)
        {
            var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
    
            app.UseStaticFiles();
            app.Run(async (context) =>
            {
                context.Response.ContentType = "text/html";
                await context.Response
                    .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                                "<title></title></head><body><p>Hosted by Kestrel</p>");
    
                if (serverAddressesFeature != null)
                {
                    await context.Response
                        .WriteAsync("<p>Listening on the following addresses: " +
                                    string.Join(", ", serverAddressesFeature.Addresses) +
                                    "</p>");
                }
    
                await context.Response.WriteAsync("<p>Request URL: " +
                                                  $"{context.Request.GetDisplayUrl()}<p>");
            });
        }
    }