Как проверить статус подключения к серверу 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 шт):
Создать банальный счётчик
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();
и вывод в консоль после этого, и увидите что оно сразу же отработает и завершится и ожидать там нечего.