2011-02-04 2 views
3

У меня есть приложение с постоянным сокетом (оно открыто, когда приложение запускается и закрывается вместе с приложением).Свойство NetworkStream.DataAvailable не возвращает правильный результат при использовании SslStream

Этот сокет используется сервером для ввода некоторых данных.

Поскольку это соединение может быть либо HTTP или HTTPS, я написал этот код, чтобы инициализировать свои объекты:

s_tcpClient = new TcpClient(s_server.CometIp, s_server.CometPort); 
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, false); 
s_tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, CST_STREAM_BUFFER_SIZE); 
s_tcpClient.ReceiveTimeout = 0; 

s_networkStream = s_tcpClient.GetStream(); 

s_cometStreamReader = null; 

if (s_server.Protocol == "HTTPS") 
{ 
    SslStream sslStream = new SslStream(
     s_tcpClient.GetStream(), 
     false, 
     new RemoteCertificateValidationCallback(ValidateServerCertificate) 
    ); 

    sslStream.AuthenticateAsClient(s_server.CometIp); 
    s_cometStreamReader = new StreamReader(sslStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE); 
    s_cometStream = sslStream as Stream; 
} 
else 
{ 
    s_cometStreamReader = new StreamReader(s_networkStream, Encoding.UTF8, true, CST_STREAM_BUFFER_SIZE); 
    s_cometStream = s_networkStream as Stream; 
} 

Таким образом, я могу обрабатывать как HTTP и HTTPS протоколы.

Затем я получил эту петлю (в потоке), который ожидает данные будут доступны в гнезде:

while (s_networkStream.DataAvailable) 
{ 
    numberOfBytesRead = s_cometStream.Read(buffer, 0, buffer.Length); 
    message.Append(Encoding.UTF8.GetString(buffer, 0, numberOfBytesRead)); 
    ExtractMessages(ref message); 
} 

Вот мои 2 вопроса:

  1. документация говорит, что метод Read возвращает 0, если данные отсутствуют. Но в моем случае, Чтение либо возвращает число> 0 (когда некоторые данные были прочитаны), либо выбрасывает исключение, потому что оно завершено ... Что мне здесь не хватает? При каких обстоятельствах Read Read 0?

  2. Когда мое соединение использует протокол HTTP, этот код работает нормально. Я получаю все, и если сообщение больше размера моего буфера (CST_STREAM_BUFFER_SIZE), DataAvailable остается истинным, и цикл считывает все остальные данные. Но когда я пытаюсь использовать HTTPS, он работает только для сообщений, меньших, чем мой буфер. Если сообщение больше, то метод Read сначала читает байты CST_STREAM_BUFFER_SIZE, а затем DataAvailable становится ложным, хотя некоторые байты, очевидно, готовы к чтению. И в этом случае получение другого сообщения «открепляет» оставшиеся данные, потому что DataAvailable снова становится истинным. Что я делаю неправильно? Почему DataAvailable не действует одинаково в обоих случаях?

Любая помощь будет принята с благодарностью.

+0

Никто не знает, что я делаю неправильно, здесь? – Rodolphe

+0

Неужели мой вопрос трудно ответить или это просто глупо? Я бы очень хотел понять, что здесь происходит ... – Rodolphe

ответ

2

Он будет возвращать только 0, если поток закрыт, и, следовательно, больше данных не будет когда-либо. В противном случае - положительное число, если данные могут быть прочитаны, что может включать блокировку, если данные пока недоступны. Если значение CanTimeout истинно, операция будет выдаваться после того, как ReadTimeout прошло без каких-либо данных.

Похоже, что сокет остался открытым и/или вы слишком много читаете, у вас есть протокол, который отправляет несколько фрагментов данных в цепочку.

http://msdn.microsoft.com/en-us/library/system.io.stream.readtimeout.aspx

+0

Хорошо, спасибо. Это отвечает на мой первый вопрос. И это действительно странное совпадение, что вы тот, кто отвечает мне, потому что вчера я попробовал вашу protobuf-net. ; o) – Rodolphe

+0

@Rodolphe - любые проблемы, дайте мне знать. –

 Смежные вопросы

  • Нет связанных вопросов^_^