[英]How to handle incoming TCP messages with a Kestrel ConnectionHandler?
[英]How to switch a ConnectionHandler to UDP
我的ASP.Net Core应用程序提供了一个TCP侦听器,该侦听器使用自定义ConnectionHandler
实施,以从另一个主机上的另一个进程(称为Datasource
)接收二进制数据。 然后,这些数据通过WebSocket(在代码中称为DataSink
)发送到浏览器。
由于Datasource
的过程已从单个TCP连接更改为UDP数据报,因此我需要进行调整(其内部无法访问)。
如何将当前实现切换到UDP侦听器? 有没有使用ASP.Net Core的规范方法?
public class MySpecialConnectionHandler : ConnectionHandler
{
private readonly IMyDataSink DataSink;
public MySpecialConnectionHandler(IMyDataSink dataSink)
{
DataSink = dataSink;
}
public override async Task OnConnectedAsync(ConnectionContext context)
{
TransportConnection connection = context as TransportConnection;
Console.WriteLine("new connection: " + connection.RemoteAddress + ":" + connection.RemotePort);
while (true)
{
var result = await connection.Transport.Input.ReadAsync().ConfigureAwait(false);
var buffer = result.Buffer;
foreach (var segment in buffer)
{
await DataSink.RelayData(segment.Span.ToArray()).ConfigureAwait(false);
}
if (result.IsCompleted)
{
break;
}
connection.Transport.Input.AdvanceTo(buffer.End);
}
Console.WriteLine(connection.ConnectionId + " disconnected");
}
}
在ASP.Net Core应用程序运行时,UDP侦听器必须可用。
编辑:
数据报传输的顺序和可靠性不是那么重要(也许一点也不重要),因为传输的数据是复用到MPEG-TS中的MPEG1流。 数据源在第一台主机上,ASP.Net Core应用程序在第二台主机上,接收器/使用者在第三台主机上。 创建流的主机和第三台主机上的接收过程位于单独的网络中。 ASP.Net Core应用程序充当中继。 发件人一直在发送,但并不关心是否已接收到数据。
编辑2:
现在的主要问题是将UdpClient放在哪里。 先前的实现(使用TCP时返回)将Kestrel服务器配置为进行其他TCP侦听,并使用了已经提供的ConnectionHandler
:
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureKestrel((_, options) =>
{
// HTTP
options.Listen(networkInterface, httpPort);
// HTTPS
options.Listen(networkInterface, httpsPort, builder => builder.UseHttps());
// stream sink
options.Listen(streamInterface, streamPort, builder => builder.UseConnectionHandler<MySpecialConnectionHandler >());
});
ConnectionHandler
接受传入的TCP连接,然后将流数据转发到许多已连接的WebSocket。 由于这不适用于UDP数据报,因此我需要将UdpClient放置在连续的位置(即while(true)
)接收数据报并将其转发到WebSockets。 我的问题是,我不知道将它放在哪里,运行后台线程并没有通信跨线程,而对此线程间数据流(例如竞争条件)没有任何问题。
因此,得出以下结论:
我们将BackgroundWorker
与UdpClient
结合使用。 仅当至少有一个接收器时才实例化BackgroundWorker
:
StreamReceiver = new BackgroundWorker();
StreamReceiver.DoWork += ReceiveStream;
StreamReceiver.RunWorkerAsync();
ReceiveStream
是建立UdpClient
的私有方法,然后等待需要中继的传入数据。
private async void ReceiveStream(object sender, DoWorkEventArgs e)
{
// DataSinkPort is a const int
UdpClient datasource = new UdpClient(_DataSinkPort);
while (true)
{
var rec = await datasource.ReceiveAsync();
await RelayData(rec.Buffer);
if (_CancellationToken.IsCancellationRequested)
{
return;
}
}
}
RelayData
方法仅使用每个订阅接收者的传出TCP连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.