Обработка разъединений WinRT StreamSocket (как на стороне сервера, так и на стороне клиента)
У меня есть приложение, которое я пишу для Windows 8 / WinRT, использующее API StreamSocket для потокового соединения с сервером. То есть сервер передает данные клиенту, иногда с метатегами, и может в любой момент отключиться.
Проблема, с которой я столкнулся, заключается в том, что я понятия не имею, как определить, когда сервер отключился. Похоже, что нет никаких событий или свойств в классе StreamSocket, ни в его входных или выходных потоках, ни в классах DataReader / DataWriter, которые имеют какое-либо отношение к состоянию соединения.
Кроме того, метод DataReader ReadAsync не завершается сбоем после того, как серверная часть отключается от клиента. Вместо этого, насколько я могу судить, операция завершается успешно, и данные, которые она заполняет в своем буфере, - это просто последнее, что сервер отправил ему (т. Е. Он не очищает свой внутренний буфер, хотя я вижу, что он имеет & quot «потребляется» буфер каждый раз, когда я вызываю ReadByte). Он делает это для каждого последующего вызова ReadAsync - пополняя буфер тем, что сервер отправил последним, прежде чем он отключился. Вот упрощенная версия кода:
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);
}
}
}
}