Как на стороне сервера можно обработать таймаут клиентов, когда тот "тихо" вырубается? На стороне клиента решил эту проблему, если сервер не посылает маленькие пакеты, но для сервера это сложнее, ибо на каждого клиента нужен поток приема пакетов и их обработка, может есть какие-другие способы, менее мои костыльные?
На каждого клиента отдельный поток. Ничего костыльного.
Чтобы не заморачиваться велосипедом, можно включить KeepAlive там и там.
В синхронном варианте это решается установкой опций сокета:
Socket.SendTimeout
Socket.ReceiveTimeout
Далее вам нужно будет обработать исключение сокета, вызванное срабатыванием таймаута соединения в вашем коде.
В асинхронном варианте (настоятельно рекомендую переписать синхронный код на асинхронный):
// Автор примера VladD, топик: https://ru.stackoverflow.com/a/505316/292443
var connectTask = socket.ConnectAsync(...);
var timeoutTask = Task.Delay(timeout);
var firstFinished = await Task.WhenAny(connectTask, timeoutTask);
if (firstFinished == timeoutTask)
{
// произошёл таймаут
}
else
{
await connectTask; // получить исключение, если есть
...
}
или
internal static async Task<TResult> TimeoutAfter<TResult>(Task<TResult> task, int timeout)
{
using (var timeoutCTS = new CancellationTokenSource())
using (var timeoutTask = Task.Delay(timeout, timeoutCTS.Token))
using (var completedTask = await Task.WhenAny(task, timeoutTask))
{
if (completedTask == task)
{
timeoutCTS.Cancel();
return await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
internal static async Task TimeoutAfter(Task task, int timeout)
{
using (var timeoutCTS = new CancellationTokenSource())
using (var timeoutTask = Task.Delay(timeout, timeoutCTS.Token))
using (var completedTask = await Task.WhenAny(task, timeoutTask))
{
if (completedTask == task)
{
timeoutCTS.Cancel();
await task; // Very important in order to propagate exceptions
}
else
{
throw new TimeoutException("The operation has timed out.");
}
}
}
Нужно передать задачу каждого действия с сокетом: ConnectAsync, SendAsync, ReceiveAsync, CloseAsync - в метод TimeoutAfter, пример использования:
await TimeoutAfter(socket.ConnectAsync(address, port), timeout);
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости