Решил вопрос, отказавших от использования в качестве проверки работы сервера TCP-соединение. (Кто может подсказать, насколько такая замена вообще могла быть жизнеспособной?).
Заменил код WaitForServerAlive() на следующий:
Код здесь
public async void WaitForServerAlive()
{
if(Debug)
Console.WriteLine($"[WARNING] [{ServerName}] Server is unavailable. Waiting for reconnection...");
IsOnline = false;
await Unwatch();
_mcQuery.InitSocket();
Timer waitTimer = null;
waitTimer = new Timer(async obj => {
try
{
await _mcQuery.GetHandshake();
IsOnline = true;
Watch();
lock (_retryCounterLock)
{
RetryCounter = 0;
}
waitTimer.Dispose();
}
catch (SocketException)
{
if(Debug)
Console.WriteLine($"[WARNING] [{ServerName}] [WaitForServerAlive] Server doesn't response. Try to reconnect: {RetryCounter}");
lock (_retryCounterLock)
{
RetryCounter++;
if (RetryCounter >= RetryMaxCount)
{
if(Debug)
Console.WriteLine($"[WARNING] [{ServerName}] [WaitForServerAlive] Recreate socket");
RetryCounter = 0;
_mcQuery.InitSocket();
}
}
}
}, null, 500, 5000);
}
Здесь каждые 5 секунд мы стучим на сервер, запрашивая новый токен. На получение токена даётся 5 попыток, после чего сокет пересоздаётся, чтобы избежать ситуаций, когда сервер поднят, a данные всё равно через сокет идти не хотят. Любой удачно переданный пакет сбрасывает счетчик. Собственно сам WaitForServerAlive() вызывается если 5 раз подряд возникла неудачная попытка получить данные с сервера, это переводит приложение в режим ожидания восстановления соединения.
Вышестоящий протокол подразумевает получение токена через хэндшейк-запрос, который возвращает результат всегда при корректно составленном запросе. Если сервер поднят, то мы получим токен. Обычно его достаточно получать раз в 30 секунд, чтобы запросы проходили. Для того, чтобы быстрее узнать о том, что сервер снова поднят, я отменяю обновление токена и вызываю похожий код раз в 5 секунд, до тех пор, пока не получу данные с сервера.
После этого можно считать что сервер снова жив и возвращаться к штатной работе.