如果没有线程睡眠,NetworkStream写入不换行

时间:2014-09-03 14:54:12

标签: c# .net sockets networkstream read-write

我有两个软件,一个是服务器,另一个是客户端界面。

在我的服务器中,我正在处理并处理请求,然后通过我写的方法返回一个字符串"回复"

    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);
}

上面的代码会将随机的换行符号写回客户端,如下所示:

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

如果我在forloop中放置了一个200ms的Thread.Sleep调用,它会正确地对响应进行换行。 在客户端,以下代码是我们从服务器读取和打印到控制台的方式:

        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 个答案:

答案 0 :(得分:2)

您的问题是客户端没有发送换行符,因此服务器基本上不知道在哪里放置换行符。 您获得“某些”换行符的事实与使用流的方式有关,NetworkStream将始终读取您在调用read时可用的任何数据,或者等到-some-数据可用;无法保证您收到的是您想要的。 您可以在应用程序的服务器端读取流中的所有数据,然后添加换行符(由于Console.WriteLine调用),然后继续阅读消息的下一部分。

我认为解决此问题的最简单方法是将reply("SOME REPLY", stream);调用更改为reply("SOME REPLY" + Environment.NewLine, stream);,然后将服务器端的Console.WriteLine调用更改为简单{{1}调用。

处理碎片或缓冲消息的更好但更复杂的方法是始终在客户端发送消息前面的“字节数”,以便服务器知道在添加之前要读取的字节数换行符:

伪代码:

Console.Write

答案 1 :(得分:1)

服务器根本不会向客户端写任何换行符,它是在读取的每个文本块之后插入换行符的客户端。

当网络流上出现某些内容时,客户端将读取当前缓冲区中的所有内容,并在此之后写入换行符。在处理该部分数据时,服务器可能有时间将若干段文本写入流中,因此下次客户端从流中读取时,它可以同时获得多个文本。

分离来自服务器的文本的唯一区别是时间差距很小,客户端没有注意到它正忙于处理之前读取的内容。您可以尝试使代码通知那些时间差距,但这远不是一个强大的解决方案。

如果您想要分开文本片段,您应该在实际流中发送一些客户端可以可靠地获取的内容。如果你只想在文本之间换行,然后从服务器发送换行符,那么客户端就可以在不添加任何内容的情况下写出它的内容。