首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在动态端口上有多个侦听器(HTTP、ConnectionHandler)的AspNetCore/Kestrel中,哪个端口对应于哪个侦听器?

问在动态端口上有多个侦听器(HTTP、ConnectionHandler)的AspNetCore/Kestrel中,哪个端口对应于哪个侦听器?
EN

Stack Overflow用户
提问于 2022-07-08 17:53:30
回答 1查看 339关注 0票数 1

我有一个NET6应用程序,它需要在任何可用端口上打开一个HTTP服务,并在另一个可用端口上使用自定义协议打开一个TCP服务。自定义协议被实现为一个ConnectionHandler。

我可以在可用端口上打开这两个服务,并且可以获得两个URL(包括端口号);但是如何确定哪个URL/端口对应于哪个服务?

详细信息和代码:

Andrew的如何在ASP.NET Core3.0中自动选择自由端口和微软的为ASP.NET核心Kestrel web服务器配置端点都描述了如何使用端口0动态绑定到可用端口,然后使用IServerAddressesFeature查找有效的URL (可以从中提取绑定端口)。

David提供了一个示例基于ASP.NET核和Kestrel的多协议服务器,它使用HTTP服务和自定义Echo处理程序(通过UseConnectionHandler())启动Kestrel。

使用这些信息,我创建了一个最小的工作NET6应用程序(如下所示)。

在我看来,除了假设IServerAddressesFeature.Addresses中的第一个元素对应于第一个so.Listen()之外,无法判断哪个服务位于哪个端口上。是否有任何方法可以确保,特别是一种不依赖于假设或目前实施的无证行为的方法?

代码语言:javascript
复制
// Minimal example of Kestrel with HTTP on dynamic port PLUS custom
// ConnectionHandler on dynamic port, and finding the port numbers.
// Connect with `curl -i %URL%`
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using System.Net;
using System.Text;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(so =>
{
  so.Listen(new IPEndPoint(IPAddress.Loopback, 0));
  so.Listen(new IPEndPoint(IPAddress.Loopback, 0),
    epo => epo.UseConnectionHandler<HttpEchoHandler>());
});

var app = builder.Build();
app.MapGet("/", () =>
{
  return "Hello, world";
});
app.Lifetime.ApplicationStarted.Register(() =>
{
  // Find ports, from https://andrewlock.net/how-to-automatically-choose-a-free-port-in-asp-net-core/
  var server = app.Services.GetRequiredService<IServer>();
  var addresses = server.Features.Get<IServerAddressesFeature>().Addresses;
  Console.WriteLine(String.Join(Environment.NewLine, addresses));
  // ******** But which endpoint is HTTP and which is Echo? ********
});
app.Run();

// Adapted from https://github.com/davidfowl/BedrockFramework/blob/main/samples/ServerApplication/EchoServerApplication.cs
class HttpEchoHandler : ConnectionHandler
{
  public override async Task OnConnectedAsync(ConnectionContext connection)
  {
    Console.WriteLine($"C{connection.ConnectionId} connected");
    var header = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n";
    var headerBytes = Encoding.ASCII.GetBytes(header);
    await connection.Transport.Output.WriteAsync(headerBytes);
    await connection.Transport.Input.CopyToAsync(connection.Transport.Output);
    Console.WriteLine($"C{connection.ConnectionId} disconnected");
  }
}
EN

回答 1

Stack Overflow用户

发布于 2022-09-03 06:16:58

你有鸡和蛋的问题。在服务器启动后,您可以知道哪些端口是绑定的,但您不知道哪些端口应用于哪一组侦听选项。您需要自己进行随机端口生成,然后告诉Kestrel,哪个随机选择了侦听选项的端口映射。

您可以使用此助手找到一个空闲端口https://github.com/dotnet/aspnetcore/blob/7f8cdfd502424215d978758d55e871e84c0457d8/src/Hosting/Server.IntegrationTesting/src/Common/TestPortHelper.cs#L22。

这样,您可以将端口和端点类型(http或tcp协议)转储到输出。将来解决这个问题的方法是在内存中查询ListenOptions,这样您就可以查询它并打印信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72915221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档