.Net Core 3.1 SignalR - Невозможно прочитать сообщения на сервере от клиента с помощью .NET Client Package - PullRequest
0 голосов
/ 22 декабря 2019

Я пытаюсь создать клиентское соединение с концентратором SignalR с помощью фоновой службы IHosted на главном сервере .net. Я хочу иметь возможность читать / обрабатывать данные, полученные от клиента signalR, как только они поступят на сервер. Представьте себе, что это способ перехвата и чтения сообщений при их передаче через концентратор сервера.

Кажется, что я мог бы добавить дополнительную логику к методам, вызываемым на сервере в классе концентратора SignalR. , но я не думаю, что это обеспечит потокобезопасную ситуацию, учитывая, что я хочу прочитать сообщения, полученные через различные соединения SignalR, и добавить содержимое сообщения в статический список, который можно проиндексировать. Содержимое сообщения будет представлять собой набор элементов, аналогичных тем, которые есть в IList, и которые я могу выполнять при добавлении / удалении и т. Д.

Документы на Microsoft пока мне не помогают, но этопоявляется с использованием последнего пакета SignalR с .NET Core 3, создание клиента .NET SignalR должно быть возможным, но примеры, которые они приводят, основаны на отдельном консольном проекте C #.

Я думаю, что проблема, которая может возникнуть у меня, частично связана с тем, как я реализую фоновую службу IHosted, т. Е. Как только соединение SignalR установлено, фоновая служба Task завершает выполнение. Кажется, что часть / логика, которую я пропускаю, - это процесс потока, который сидит и ждет, пока не придет сообщение, затем высасывает содержимое и делает все, что я решу оттуда.

Сам концентратор SignalR ипример клиентского чата в браузере, который я использовал от Microsoft, работает нормально, используя страницу тестовой бритвы, поэтому проблема вряд ли будет в хабе.

В приведенном ниже разделе кода службы IHosted я вижу первое событие журнала "STARTING SIGNALR at ... "генерируется при первом запуске фоновой службы, но, глядя на консоль отладки, похоже, что задача службы завершается после установления соединения SignalR, и больше ничего не делается. Я понимаю, что мой подход к этому, скорее всего, неверен, мне удобно с SignalR, когда все, что я делаю, это передаю данные между конечными точками клиента через клиент браузера, используя javascript, но это требование требует другого подхода и плохо документировано.

 namespace MyProjectNamespace.Classes.Events
 {
  public class SystemEventsService : IHostedService
  {
    // Create an instance of a CancellationTokenSource that will be used to stop the system mappings from running.
    public static CancellationTokenSource cancelSource;

    private readonly ILogger<SystemEventsService> _logger;

    public SystemEventsService(ILogger<SystemEventsService> logger)
    {
        _logger = logger;
    }

    HubConnection connection;

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        connection = new HubConnectionBuilder()
            .WithUrl("http://localhost:44372/dataHub")
            .WithAutomaticReconnect()
            .Build();

        _logger.LogInformation("STARTING SIGNALR at {Time}", DateTime.UtcNow);

        connection.On<string, string>("ReceiveMessage", (user, message) =>
        {
            _logger.LogInformation("String [" + message + "] received on server side at {Time}", DateTime.UtcNow);
        });

        connection.Closed += async (error) =>
        {
            await Task.Delay(new Random().Next(0, 5) * 1000);
            await connection.StartAsync();
        };

        try
        {
            await connection.StartAsync();
        }
        catch (Exception ex)
        {
            _logger.LogInformation(ex.Message, DateTime.UtcNow);
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
  }
}

Файл Program.CS, где я запускаю фоновую службу:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
        .ConfigureLogging((context, logging) =>
        {
            logging.ClearProviders();
            logging.AddConfiguration(context.Configuration.GetSection("Logging"));
            logging.AddDebug();
            logging.AddConsole();
            // EventSource, EventLog, TraceSource, AzureAppServicesFile, AzureAppServicesBlob, ApplicatioInsights
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        })
        .ConfigureServices(services =>
        {
            services.AddHostedService<SystemEventsService>(); // This the service
        });

Страница Razor - клиент Javascript (работает нормально)

    <div class="container">
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-2">User</div>
        <div class="col-4"><input type="text" id="userInput" /></div>
    </div>
    <div class="row">
        <div class="col-2">Message</div>
        <div class="col-4"><input type="text" id="messageInput" /></div>
    </div>
    <div class="row">&nbsp;</div>
    <div class="row">
        <div class="col-6">
            <input type="button" id="sendButton" value="Send Message" />
        </div>
    </div>
</div>
<div class="row">
    <div class="col-12">
        <hr />
    </div>
</div>
<div class="row">
    <div class="col-6">
        <ul id="messagesList"></ul>
    </div>
</div>

<script src="~/js/signalr/dist/browser/signalr.js"></script>

    <script>
    var connection = new signalR.HubConnectionBuilder().withUrl("/dataHub").build();

    //Disable send button until connection is established
    document.getElementById("sendButton").disabled = true;

    connection.on("ReceiveMessage", function (user, message) {
        var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        var encodedMsg = user + " says " + msg;
        var li = document.createElement("li");
        li.textContent = encodedMsg;
        document.getElementById("messagesList").appendChild(li);
    });

    connection.start().then(function () {
        document.getElementById("sendButton").disabled = false;
    }).catch(function (err) {
        return console.error(err.toString());
    });

    document.getElementById("sendButton").addEventListener("click", function (event) {
        var user = document.getElementById("userInput").value;
        var message = document.getElementById("messageInput").value;
        connection.invoke("SendMessage", user, message).catch(function (err) {
            return console.error(err.toString());
        });
        event.preventDefault();
    });
</script>

SignalRКласс ступицы:

public class DataHub : Hub
{

    private readonly ILogger<DataHub> _logger;

    public DataHub(ILogger<DataHub> logger)
    {
        _logger = logger;
    }


    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
        _logger.LogInformation("String [" + message + "] received on server hub at {Time}", DateTime.UtcNow);
    }
}
...