Обработка разъединений WinRT StreamSocket (как на стороне сервера, так и на стороне клиента)

У меня есть приложение, которое я пишу для Windows 8 / WinRT, использующее API StreamSocket для потокового соединения с сервером. То есть сервер передает данные клиенту, иногда с метатегами, и может в любой момент отключиться.

Проблема, с которой я столкнулся, заключается в том, что я понятия не имею, как определить, когда сервер отключился. Похоже, что нет никаких событий или свойств в классе StreamSocket, ни в его входных или выходных потоках, ни в классах DataReader / DataWriter, которые имеют какое-либо отношение к состоянию соединения.

Кроме того, метод DataReader ReadAsync не завершается сбоем после того, как серверная часть отключается от клиента. Вместо этого, насколько я могу судить, операция завершается успешно, и данные, которые она заполняет в своем буфере, - это просто последнее, что сервер отправил ему (т. Е. Он не очищает свой внутренний буфер, хотя я вижу, что он имеет & quot «потребляется» буфер каждый раз, когда я вызываю ReadByte). Он делает это для каждого последующего вызова ReadAsync - пополняя буфер тем, что сервер отправил последним, прежде чем он отключился. Вот упрощенная версия кода:

<code>    public async Task TestSocketConnectionAsync()
    {
        var socket = new StreamSocket();
        await socket.ConnectAsync(new HostName(Host), Port.ToString(),
            SocketProtectionLevel.PlainSocket);
        var dr = new DataReader(socket.InputStream);
        dr.InputStreamOptions = InputStreamOptions.Partial;

        this.cts = new CancellationTokenSource();
        this.listenerOperation = StartListeningAsync(dr, cts);
    }

    public async Task StartListeningAsync(DataReader dr, CancellationTokenSource cts)
    {
        var token = cts.Token;
        while (true)
        {
            token.ThrowIfCancellationRequested();
            var readOperation = dr.LoadAsync(1024);
            var result = await readOperation;
            if (result <= 0 || readOperation.Status != Windows.Foundation.AsyncStatus.Completed)
            {
                cts.Cancel(); // never gets called, status is always Completed, result always > 0
            }
            else
            {
                while (dr.UnconsumedBufferLength > 0)
                {
                    byte nextByte = dr.ReadByte();

                    // DriveStateMachine(nextByte);
                }
            }
        }
    }
</code>

Ответы на вопрос(1)

Ваш ответ на вопрос