Не получает все данные с networkstream.read - PullRequest
0 голосов
/ 11 декабря 2011

Я использую следующий код для получения групп новостей с сервера:

sendBytes = Encoding.ASCII.GetBytes("LIST active microsoft.public*" & ControlChars.CrLf)
networkStream.Write(sendBytes, 0, sendBytes.Length)
Array.Clear(bytes, 0, bytes.Length)
If networkStream.CanRead Then
    Do
        numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length)
        myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))
        intLenMyReadBuf = myReadBuffer.Length
        intLenComplMsg = myCompleteMessage.Length
        swWriter.WriteLine("buf len = " & intLenMyReadBuf & ", msg len = " & intLenComplMsg)
        Loop While networkStream.DataAvailable
Else
    Console.WriteLine("Sorry.  You cannot read from this NetworkStream.")
End If

sendBytes = Encoding.ASCII.GetBytes("QUIT " & ControlChars.CrLf)
networkStream.Write(sendBytes, 0, sendBytes.Length)
tcpClient.Close()
networkStream.Close()

Когда я выполняю код, процедура получает только один блок данных.Однако, если я перехожу в режим отладки с точкой останова в инструкции цикла, я получаю все блоки данных.
Я что-то упускаю в коде, например, ожидание или что-то такое, что позволило бы программе
получить все данные, как это происходит с отладкой?

1 Ответ

1 голос
/ 12 декабря 2011

Проблема в том, что вы зацикливаетесь, пока networkStream.DataAvailable не станет верным.В работающем приложении ваш цикл может выполняться так быстро, что отправитель не успеет снова заполнить буфер.

Вы должны либо выполнить цикл, пока не будет выполнено определенное условие.Примеры:

1) Все ожидаемые данные были получены

2) Получен определенный набор данных (т. Е. EOF)

3) Определенныйсрок был достигнут (т.е. если вы не получили никаких данных в течение 30 секунд, залог).Если вы находитесь в бесконечном цикле, вы всегда должны реализовывать что-то подобное, если только вы не намерены продолжать процесс вечно.

Я бы изменил обработку на что-то вроде:

Dim fLoopDone As Boolean
' Initialize the timestamp for the last data that was read so that we wait up to 30 seconds
' at the start for data.
Dim dtLastData As DateTime = Date.Now
Do
    ' Only process the data if there is some available.
    If networkStream.DataAvailable Then
        numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length)
        myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))
        intLenMyReadBuf = myReadBuffer.Length
        intLenComplMsg = myCompleteMessage.Length
        swWriter.WriteLine("buf len = " & intLenMyReadBuf & ", msg len = " & intLenComplMsg)

        ' Record the last time that we received data
        dtLastData = Date.Now

        ' Possibly add a check in here to see if you are done reading.
    Else
        ' If more than 30 seconds has elapsed since the last data arrived, break out of the loop
        If Date.Now.Subtract(dtLastData).TotalSeconds > 30 Then
           fLoopDone = True
        End If
    End If
Loop While Not fLoopDone
...