В UWP StreamSocket могу ли я читать данные с тайм-аутом и оставлять соединение открытым, если тайм-аут истек

Поскольку я не мог найти способ просмотреть данные (прочитать данные без использования буфера), как было задано в Как просматривать StreamSocket для данных в приложениях UWP Сейчас я пытаюсь сделать свой собственный "просмотр", но пока безуспешно.

Я не понимаю, как я могу читать данные из StreamSocket таким образом, который позволит мне использовать тайм-ауты и оставить соединение пригодным для использования в случае истечения тайм-аута.

В итоге проблема в следующем. В моем, скажем, IMAP-клиенте я получаю ответ от сервера, и если этот ответ отрицательный, мне нужно немного подождать, чтобы увидеть, отправит ли сервер немедленно еще один ответ (иногда сервер может это сделать, с дополнительными подробностями об ошибке или даже нулевом пакете, чтобы закрыть соединение). если сервер не отправил другого ответа, я в порядке, просто оставляю метод и возвращаюсь к вызывающему. Затем вызывающий абонент может отправить больше данных в поток, получить больше ответов и т. д.

Итак, после отправки запроса и получения первоначального ответа мне нужно в некоторых случаях прочитать сокет еще раз с очень маленьким интервалом ожидания, и если данные не приходят, просто ничего не делать.


person Alex    schedule 03.03.2017    source источник


Ответы (1)


Вы можете использовать CancelationTokenSource, чтобы сгенерировать тайм-аут и остановить операцию async. DataReader использует данные из входных поток StreamSocket. Его метод LoadAsync() вернется, когда будет хотя бы один байт данных. Здесь мы добавляем источник отмены, который отменит асинхронную задачу через 1 секунду, чтобы остановить DataReader.LoadAsync(), если данные не были использованы.

var stream      = new StreamSocket();

var inputStream = stream.InputStream;

var reader      = new DataReader(inputStream);
reader.InputStreamOptions   = InputStreamOptions.Partial;

while(true)
{
    try
    {
        var timeoutSource   = new CancellationTokenSource(TimeSpan.FromSeconds(1));
        var data    = await reader.LoadAsync(1).AsTask(timeoutSource.Token);

        while(reader.UnconsumedBufferLength > 0)
        {
            var read    = reader.ReadUInt32();
        }
    }
    catch(TaskCanceledException)
    {
        // timeout
    }
}

Не забывайте, что удаление DataReader закроет поток и соединение.

person Vincent    schedule 03.03.2017
comment
Спасибо. Но как я могу избавиться от DataReader после того, как он выполнил свою работу? Затем мне нужно будет вернуть соединение вызывающему абоненту в том же состоянии, что и раньше. В идеале мне нужно иметь возможность подключать его к существующему соединению и отключать его несколько раз в течение времени жизни соединения. - person Alex; 04.03.2017
comment
Вы можете отсоединить поток от средства чтения с помощью DetachStream() : noreferrer">docs.microsoft.com/en-us/uwp/api/. Это позволит вам держать поток открытым при удалении считывателя. - person Vincent; 05.03.2017
comment
Ой, проверяя DataReader, я обнаружил, что уже использую его в другом своем коде ровно для той же цели и, кажется, совсем забыл, что уже решал эту задачу раньше, буквально несколько месяцев назад.. Невероятно. . - person Alex; 06.03.2017