Установите тайм-аут при чтении NetworkStream с TcpClient - PullRequest
0 голосов
/ 16 февраля 2012

Я реализовал TCP-клиент для подключения к серверу с помощью TcpClient ( C # .NET 4 ):

// TCP client & Connection
TcpClient client = new TcpClient();
client.Connect(new IPEndPoint(IPAddress.Parse(IP), PORT));
NetworkStream clientStream = client.GetStream();

// Get message from remote server
byte[] incomingBuffer = new byte[1024];
Int32 bytes = clientStream.Read(incomingBuffer, 0, incomingBuffer.Length);
string problesWithThis = System.Text.Encoding.ASCII.GetString(incomingBuffer, 0, bytes);

Подключение к серверу работает хорошо. Но я могу прочитать только часть ответа с сервера, и недоставленная часть сообщения будет прочитана при следующей попытке подключения .

Я пытался установить время ожидания NetworkStream:

// No change for me   
clientStream.ReadTimeout = 10000;

Затем я попытался смоделировать время ожидания:

// This works well, the client has enough time to read the answers. But it's not the right solution.

// ....

NetworkStream clientStream = client.GetStream();
Thread.Sleep(TimeSpan.FromSeconds(1));

// Read stream ....

1 Ответ

4 голосов
/ 16 февраля 2012

Данные передаются по TCP в пакетах, которые поступают последовательно (но не обязательно в правильной последовательности).Сразу же, когда данные доступны, т.е. когда логически (если не хронологически) следующий пакет получен, clientStream.Read() вернется с данными в этом (и, возможно, любом другом oo-последовательности) пакете (ах) - независимо от того, все ли этоданные, которые отправляющая сторона отправила или нет.

Ваш Thread.Sleep() заставляет программу ждать секунду - за это время более одного пакета поступает и буферизуется на системном уровне, поэтому вызов clientStream.Read()немедленно вернется с доступными данными.

Правильный способ справиться с этим - это зациклить ваш Read() до тех пор, пока BytesAvailable() не станет равным нулю или пока не будет обнаружен полный элемент протокола уровня приложения.

...