[英]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.