TCPclient таймаут соединения

190
04 апреля 2018, 08:18

Как на стороне сервера можно обработать таймаут клиентов, когда тот "тихо" вырубается? На стороне клиента решил эту проблему, если сервер не посылает маленькие пакеты, но для сервера это сложнее, ибо на каждого клиента нужен поток приема пакетов и их обработка, может есть какие-другие способы, менее мои костыльные?

Answer 1

На каждого клиента отдельный поток. Ничего костыльного.

Чтобы не заморачиваться велосипедом, можно включить KeepAlive там и там.

Answer 2

В синхронном варианте это решается установкой опций сокета:

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);
READ ALSO
Некорректное отображение DataGridView

Некорректное отображение DataGridView

Создала приложение которое добавляет строчки в DataGridView по событиям одновременно задается раскраска

210
Как установить AvalonDock?

Как установить AvalonDock?

Пытаюсь прикрепить AvalonDock к проектуТам архив в котором архив с source code, как собрать и использовать в WPF проекте?

164
Tlsharp ConnectAsync

Tlsharp ConnectAsync

Когда я вызываю clientConnectAsync() моя программа останавливается

223
progressBar и Marquee

progressBar и Marquee

Не работает прогресс бар типа MarqueeПо нажатию кнопку использую код:

228