TcpClient没有返回读取的所有行

时间:2014-02-28 20:30:17

标签: c# tcpclient

尝试使用TcpClient类从远程主机获取一些文本。想要遍历stream.Read,直到我得到所有数据。如果我使用bytesRead > 0,它就会挂起。如果我运行此代码,我只从远程主机获得第一行输出,程序正常退出。但是,如果我在do循环中的第一行中断并在调试器中手动逐步执行每次迭代,我最终会得到我预期的所有行。我真的不明白为什么会这样。这是我正在使用的代码:

            TcpClient client = new TcpClient("myserver.net", 1234);
            NetworkStream stream = client.GetStream();

            Byte[] buffer = new Byte[256];

            StringBuilder sb = new StringBuilder();
            int bytesRead;
            do
            {
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                sb.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead));
            } while (bytesRead == 256);

只要添加,如果我有目的地等待每次迭代的额外时间,它似乎得到我想要的,但我不明白为什么会这样......

            StringBuilder sb = new StringBuilder();
            int bytesRead;
            do
            {
                System.Threading.Thread.Sleep(500);
                bytesRead = stream.Read(buffer, 0, buffer.Length);
                sb.Append(System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead));
            } while (bytesRead == 256);

2 个答案:

答案 0 :(得分:1)

它在调试器中工作的原因是因为您正在减慢代码的速度以允许网络缓冲区填满。当你调用stream.Read并传入256(buffer.Length)的长度时,它只是告诉流读取缓冲区中的任何内容,直到该长度。如果缓冲区中只有100个字节,它只会读取100个字节,返回值将为100.这很可能发生了(缓冲区没有完整的256字节可用),所以你的{{1}条件不再满足,它正在打破循环。

考虑到这一点,如果没有某种协议,“所有数据”都不是您可以保证的。流本身可以随时在其缓冲区(从您的角度)显示数据。您需要实现某种长度规范(基本上为您的消息提供一个头结构,其中一部分描述了消息的可变长度部分的长度)或某种保留的字节或字节序列。充当终结者。然后你知道要么读取一个特定的字节数(除非你想抛出异常,否则你不会退出)或者你知道在你遇到终结符字节或字节序列之前要读取它。

答案 1 :(得分:1)

如评论中所述,只需使用StreamReader

TcpClient client = new TcpClient();
client.Connect("myserver.net", 1234);

var stream = new StreamReader(client.GetStream(),Encoding.ASCII);
string line = null;
while ((line = stream.ReadLine()) != null)
{
    Console.WriteLine(line);
}