Как переключить ConnectionHandler на UDP - PullRequest
1 голос
/ 18 июня 2019

Мое приложение 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");
    }
}

Прослушиватель UDP должен быть доступен во время работы приложения ASP.Net Core.

EDIT:

Порядок и надежность передачи дейтаграммы не так важны (возможно, вообще не важны), поскольку передаваемые данные представляют собой поток MPEG1, мультиплексированный в MPEG-TS.Источник данных находится на первом хосте, приложение 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-соединение и затем пересылает потоковую передачуданные для нескольких подключенных WebSockets.Поскольку это невозможно использовать с дейтаграммами UDP, мне нужно поместить UdpClient где-нибудь, где он непрерывно (т.е. while(true)) получает дейтаграммы и передает их в WebSockets.Моя проблема в том, что я не знаю, где его разместить, запустить фоновый поток и иметь потоки коммуникационного потока, не имея проблем с этим потоком данных между потоками (например, в условиях гонки).

1 Ответ

0 голосов
/ 24 июня 2019

Итак, чтобы сделать вывод:

Мы использовали комбинацию 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-соединение каждого подписанного получателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...