Почему я все еще получаю данные даже после того, как NetworkStream.EndRead возвращает 0 байтов? - PullRequest
3 голосов
/ 21 марта 2012

Я использую NetworkStream.BeginRead / EndRead для асинхронного чтения из сокета.

Однако NetworkStream.EndRead () иногда возвращает 0 (т. Е. Из сокета было прочитано 0 байт), что, как я думал, указывает на то, что сокет был закрыт, но это не так, потому что если я продолжу вызывать BeginRead (), в конце концов получу больше данных.

Разве это не правильный цикл для непрерывного чтения данных из сокета / NetworkStream?

void BeginContinousRead()
{
  // Start the continous async read
  mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}

private void ProcessNetworkStreamRead(IAsyncResult result)
{
  // This will sometimes be zero?!
  int bytesRead = mStream.EndRead(result);

  // Continue reading more data and call this callback method again over and over, etc.
  mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}

Согласно MSDN, я должен использовать свойство NetworkStream.DataAvailable, чтобы определить, доступно ли больше данных в сокете, но это будет ЛОЖЬ, даже если больше данных может поступить позднее.

Например, согласно MSDN это должен быть мой обратный вызов:

private void ProcessNetworkStreamRead(IAsyncResult result)
{
  // This will sometimes be zero?!
  int bytesRead = mStream.EndRead(result);

  while (mStream.DataAvailable)
    mStream.BeginRead(mDataBuffer, 0, mDataBuffer.Length, new AsyncCallback(ProcessNetworkStreamRead), null);
}

... но это не работает должным образом, потому что DataAvailable становится ЛОЖНЫМ, и тогда мое непрерывное чтение останавливается и никогда не читает больше данных.

Каков правильный асинхронный подход для продолжения чтения данных, пока другой конец не закроет сокет или я не решу закрыть сокет?

1 Ответ

0 голосов
/ 21 марта 2012

Вместо проверки bytesRead или свойства DataAvailable, чтобы проверить, закрыт ли сокет, оберните вызов BeginRead и перехватите IOException.Это должно сказать вам, если сокет закрыт.

...