Как проверить статус подключения к серверу UDP C#

Мне нужно раз в 5 секунд слать определенный пакет LinkStatus на сервер по UDP. При этом если ответа от сервера не приходит более 5 раз подряд, нужно уведомить об этом пользователя и попытаться восстановить подключение.

Я сделал обертку вокруг UdpClient, где есть методы: Для подключения

public void Connect()
{
    _client.Connect(new IPEndPoint(_ipAddress, _port));
    StartReceiveAsync();
}

Для отключения

public void Disconnect()
{
    _client.Dispose();
}

Для отправки пакетов:

public async Task SendAsync(IRequest request)
{
    await _client.SendAsync(request.Bytes);
}

Для получения пакетов в отдельном потоке:

private void StartReceiveAsync()
    {
        var receive = new Task(async () => 
        {
            try
            {
                while (true)
                {
                    var receivedResults = await _client.ReceiveAsync();
                    Notify?.Invoke(receivedResults.Buffer);
                }
            }
            catch
            {
                Console.WriteLine("Прием сообщений был прерван");
            }

        }, TaskCreationOptions.LongRunning);

        receive.Start();
    }

Работа с этой оберткой осуществляется в отдельном сервисе. Как будет лучше реализовать метод для отправки запросов на статус подключения в сервисе, проверять сколько раз ответ не был получен и завершать поток, который принимает сообщения от сервера?


Ответы (1 шт):

Автор решения: aepot

Создать банальный счётчик

private int count = 0;

При отправке

public async Task SendAsync(IRequest request)
{
    await _client.SendAsync(request.Bytes);
    count++;
}

При получении

while (true)
{
    var receivedResults = await _client.ReceiveAsync();
    Notify?.Invoke(receivedResults.Buffer);
    count = 0;
}

Осталось найти место, где выполнить проверку, при отправке, по таймеру или как вам удобнее.

if (count >= 5)
{
    // нужно уведомить об этом пользователя и попытаться восстановить подключение
    count = 0;
}

Почитайте ещё это: Создание бесконечно повторяющегося метода в c#


Смысла создавать LongRunning таск, если у вас он такой один, никакого. Используйте простой Task.Run вместо конструктора Task. Даже больше скажу, здесь и поток не нужен в целом.

private async void StartReceiveAsync()
{
    try
    {
        while (true)
        {
            var receivedResults = await _client.ReceiveAsync();
            Notify?.Invoke(receivedResults.Buffer);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Прием сообщений был прерван: {ex.Message}");
    }
}

К тому же, сейчас внимательно взглянул, ваш LongRunning таск работает всего-лишь несколько миллисекунд, и завершается при входе в первый же await. Потому что async делегат у вас async void, так как конструктор Task не принимает async Task(Func<Task>) делегаты, просто нет такой перегрузки. То есть вы принудительно спавните поток, который потом сразу же выбрасываете. Это просто лишнее. Проверить легко, сделайте await receive; или receive.Wait(); и вывод в консоль после этого, и увидите что оно сразу же отработает и завершится и ожидать там нечего.

→ Ссылка