【问题标题】:How to determine which port ASP.NET Core 2 is listening on when a dynamic port (0) was specified如何在指定动态端口 (0) 时确定 ASP.NET Core 2 正在侦听的端口
【发布时间】:2018-02-27 21:51:51
【问题描述】:

我有一个 ASP.NET Core 2.0 应用程序,我打算将其作为独立应用程序运行。该应用程序应启动并绑定到可用端口。为此,我将 WebHostBuilder 配置为侦听“http://127.0.0.1:0”并使用 Kestrel 服务器。一旦网络主机开始侦听,我想将带有实际端口的 url 保存在文件中。我想尽早这样做,因为另一个应用程序会读取该文件以与我的应用程序交互。

如何确定网络主机正在侦听的端口?

【问题讨论】:

    标签: kestrel-http-server asp.net-core-2.0


    【解决方案1】:

    我可以使用反射来做到这一点(啊!)。我注册了IHostedService 并注入了IServerKestrelServerOptions 上的 ListenOptions 属性是内部的,因此我需要使用反射来获取它。当调用托管服务时,我使用以下代码提取端口:

    var options = ((KestrelServer)server).Options;
    var propertyInfo = options.GetType().GetProperty("ListenOptions", BindingFlags.Instance | BindingFlags.NonPublic);
    var listenOptions = (List<ListenOptions>)propertyInfo.GetValue(options);
    var ipEndPoint = listenOptions.First().IPEndPoint;
    var port = ipEndPoint.Port;
    

    【讨论】:

      【解决方案2】:

      你可以在 Startup 类的 Configure 方法中实现它。您可以从 ServerAddressesFeature 获取端口

      下面是代码示例:

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ILogger<Startup> logger)
      {
           var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
      
           loggerFactory.AddFile("logs/myfile-{Date}.txt", minimumLevel: LogLevel.Information, isJson: false);
      
           logger.LogInformation("Listening on the following addresses: " + string.Join(", ", serverAddressesFeature.Addresses));
      }
      

      【讨论】:

      • 有 0 个地址,有什么想法吗?
      • 你确定@jjxtra 吗?它是枚举器,所以你必须这样做:foreach (var address in serverAddressesFeature.Addresses) Console.WriteLine(address.ToString());
      • 仅供参考,不幸的是,当通过 Http.Sys 托管时,这似乎没有获取 url 前缀。
      【解决方案3】:

      你可以使用Start()方法代替Run()在适当的时候访问IServerAddressesFeature

      IWebHost webHost = new WebHostBuilder()
          .UseKestrel(options => 
               options.Listen(IPAddress.Loopback, 0)) // dynamic port
          .Build();
      
      webHost.Start();
      
      string address = webHost.ServerFeatures
          .Get<IServerAddressesFeature>()
          .Addresses
          .First();
      int port = int.Parse(address.Split(':').Last());
      
      webHost.WaitForShutdown();
      

      【讨论】:

      • 不要使用Console.ReadKey(),而是使用webHost.WaitForShutdown()
      • 您应该使用int.Parse(address.Split(':').Last());,因为该地址可以定义为 IPv6 地址
      • 如果您想在获得地址之前在控制台/输出中打印默认消息,也可以使用webHost.RunAsync() 而不是webHost.Start()
      【解决方案4】:

      我可以使用以下代码在 StartUp.cs 中完成此操作:

      int Url = new System.Uri(Configuration["urls"]).Port;
      

      【讨论】:

      • 如果你监听两个端口(一个用于 HTTP,另一个用于 HTTPS),这将不起作用
      • 使用 .NET Core 3.1 Configuration["urls"]Startup.Configure() 中返回 null 所以这个建议似乎不起作用。
      【解决方案5】:

      至少可以从 .Net Core 3 中注入 IServer 并获取信息。

      using System;
      using System.Linq;
      using Microsoft.AspNetCore.Hosting.Server;
      using Microsoft.AspNetCore.Hosting.Server.Features;
      
      namespace MyApp.Controllers
      {
          public class ServerInfoController : Controller
          {
              public ServerInfoController (IServer server)
              {
                  var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses?.ToArray();
              }
          }
      }
      

      【讨论】:

      • 这是一个不完整的答案.. 无法解析类型“Microsoft.AspNetCore.Hosting.Server.IServer”的服务
      • @GabrielLuca 如果没有调用WebHost.CreateDefaultBuilderIServer 可能会出现问题。 ConfigureKestrel 不注册 IServerUseKestrelCreateDefaultBuilder 注册。
      • 我也调用了 WebHost.CreateDefaultBuilder 并且仍然无法正常工作......我会收回我的反对票,因为...... M$ 改变事情的方式很奇怪,而且这么简单的事情很难......得到..除非你改变答案,否则我不能改变我的投票......它不允许我..
      • 如果你可以让它工作..发布一个小样本会有所帮助..
      猜你喜欢
      • 2021-12-16
      • 2023-03-12
      • 1970-01-01
      • 2014-08-03
      • 2022-09-24
      • 2011-02-19
      • 2017-11-03
      • 1970-01-01
      • 2013-07-22
      相关资源
      最近更新 更多