Manipulando desconexões do WinRT StreamSocket (do lado do servidor e do cliente)
Eu tenho um aplicativo que estou escrevendo para o Windows 8 / WinRT que usa a API StreamSocket para fazer uma conexão de streaming para um servidor. Ou seja, o servidor transmite dados para o cliente, às vezes com metatags e pode desconectar a qualquer momento.
O problema que estou tendo é que eu não tenho idéia de como detectar quando o servidor foi desconectado. Não parece haver nenhum evento ou propriedade na classe StreamSocket, seus fluxos de entrada ou saída, ou nas classes DataReader / DataWriter que têm alguma coisa a ver com o status da conexão.
Além disso, o ReadAsync do método DataReader não está falhando depois que o lado do servidor se desconecta do cliente. Em vez disso, a operação é bem-sucedida, e os dados que ela preenche em seu buffer são apenas a última coisa que o servidor enviou para ela (ou seja, não está limpando seu buffer interno, embora eu possa ver que ela "consumiu" o buffer cada vez que eu chamo ReadByte). Ele faz isso para cada chamada subseqüente ao ReadAsync - recarregando o buffer com o que o servidor enviou por último antes de ser desconectado. Aqui está uma versão simplificada do código:
<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>