在AspNetCore/Kestrel与多个监听器(HTTP, ConnectionHandler)在动态端口,哪个端口



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

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

详细信息和代码:

Andrew Lock的《如何在ASP中自动选择空闲端口》。. NET Core 3.0和微软的配置端点。. NET Core Kestrel web server描述了如何使用Port 0动态绑定到一个可用的端口,然后使用IServerAddressesFeature找到有效的URL(可以从中提取绑定端口)。

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

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

在我看来,除了假设IServerAddressesFeature.Addresses中的第一个元素对应于第一个so.Listen()之外,没有办法告诉哪个服务在哪个端口上。是否有任何方法可以确定,特别是不依赖于当前实现的假设或未记录的行为的方法?

// 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 OKrnConnection: closernContent-Type: text/htmlrnrn";
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");
}
}

这是鸡生蛋还是蛋生鸡的问题。您可以知道服务器启动后绑定了哪些端口,但不知道哪些端口应用于哪组侦听选项。你需要做随机端口一代自己然后告诉红隼哪个随机选择的端口映射到哪个听选项。

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

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

相关内容

  • 没有找到相关文章

最新更新