2014-09-03 4 views
0

У меня есть два программного обеспечения, один из которых сервер, а другой - клиентский интерфейс.NetworkStream write not newlining if not thread slept

В моем сервере я беру и обработку запроса затем возвращает строку через метод, который я написал «ответ»

public static void reply(string buffer, NetworkStream stream) 
    { 
     stream.Write(Encoding.ASCII.GetBytes(buffer), 0, buffer.Length); 
    } 

вопрос я имею, что, например, если бы я, чтобы сделать код ниже

for(int i = 0; i<5; i++){ 
reply("SOME REPLY", stream); 
} 

приведенный выше код будет писать случайные newlined строки обратно клиенту, как это:

SOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLYSOME REPLYSOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLY 

Если бы я поставил 200 мс Thread.Sleep-вызов в forloop, он бы корректно набросал ответы. На стороне клиента ниже код, как мы читаем с сервера и печати на консоль:

 Byte[] bytes = new Byte[256]; 
     NetworkStream stream = endpoint.GetStream(); 
     int i; 
     while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
     { 
      Console.WriteLine(System.Text.Encoding.ASCII.GetString(bytes, 0, i)); 
     } 

ответ

2

Ваша проблема заключается в том, что клиент не посылает символ новой строки, так что сервер в принципе не имеет понятия, куда поставьте новые строки. Тот факт, что вы получаете «некоторые» символы новой строки, связан с тем, как используется поток, NetworkStream всегда будет читать любые данные, доступные при вызове чтения, или ждать, пока доступны некоторые данные; нет никакой гарантии, что то, что вы получаете, - это то, что вы хотите. Вы можете прочитать все данные из потока на стороне сервера в своем приложении, а затем добавить новую строку (из-за вызова Console.WriteLine), а затем продолжить чтение следующей части сообщения.

Я полагаю, самый простой способ обойти это просто изменить reply("SOME REPLY", stream); вызов reply("SOME REPLY" + Environment.NewLine, stream);, а затем изменить Console.WriteLine вызов на стороне сервера до простого Console.Write вызова.

Лучше, но немного более сложный способ обработки фрагментированных или буферизованных сообщений заключается в том, чтобы всегда отправлять «байтовый счет» перед своим сообщением с клиентской стороны, чтобы сервер знал, сколько байтов для чтения до добавление новой строки:

псевдокод:

Client => Send([number of bytes] + [data]) 
Server => Read([number of bytes] (Field)) 
Server => Read([data]) until received bytes count == [number of bytes] 
+0

Здесь полезно использовать ['BinaryWriter'] (http://msdn.microsoft.com/en-us/library/yzxa6408 (v = vs.110) .aspx). Он записывает для вас длину байтов длины. –

+0

Спасибо, я действительно пробовал делать «\ n» без успеха, но я не верю, что переключился на использование «writ» над «writeline». Ваше исправление отлично работает. – user2887749

+0

Если вы находитесь в Windows, \ n нужно будет \ r \ n - особенно в .NET. См. Свойство Environment.NewLine. – t0yk4t

1

сервер не пишет никаких новых строк вообще к клиенту, это клиент, который вставляет новые строки после каждого блока текста, который он читает.

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

Единственное, что отделяет фрагменты текста, поступающего с сервера, - это крошечный промежуток времени, и клиент не заметил, что, поскольку он был занят обработкой того, что он читал до этого. Вы могли бы попытаться сделать код значащим эти промежутки времени, но это далеко не надежное решение.

Если вы хотите отделить фрагменты текста, вы должны отправить что-то в фактическом потоке, который клиент может надежно подобрать. Если вам просто нужен разрыв строки между текстом, затем отправьте разрывы строк с сервера, тогда клиент может просто записать, что он получает, не добавляя к нему ничего.