2
        NetworkStream stream = socket.GetStream();

        if (stream.CanRead)
        {
            while (true)
            {
                int i = stream.Read(buf, 0, 1024);
                result += Encoding.ASCII.GetString(buf, 0, i);
            }
        }

上面的代码旨在从TcpClient在单独线程上运行时检索消息。Read方法工作正常,直到它应该返回 -1 表示没有什么可读取的了;相反,它只是在没有任何明显原因的情况下终止它正在运行的线程 - 使用调试器跟踪每个步骤表明它只是在该行之后停止运行。

我也尝试用 a 封装它但try ... catch没有多大成功。

这可能是什么原因造成的?

编辑:我试过

        NetworkStream stream = socket.GetStream();

    if (stream.CanRead)
    {
        while (true)
        {
            int i = stream.Read(buf, 0, 1024);
            if (i == 0)
            {
                break;
            }
            result += Encoding.ASCII.GetString(buf, 0, i);
        }
    }

感谢@JonSkeet,但问题仍然存在。线程在该read行终止。

EDIT2:我修复了这样的代码并且它有效。

    while (stream.DataAvailable)
    {
        int i = stream.Read(buf, 0, 1024);
        result += Encoding.ASCII.GetString(buf, 0, i);
    }

我觉得问题很简单,只是我想的不够透彻。感谢大家看这个!

4

3 回答 3

5

不,Stream.Read当没有可读取的内容时返回 0,而不是 -1:

返回值
读入缓冲区的总字节数。如果当前没有那么多字节可用,则该字节数可能小于请求的字节数,如果已到达流的末尾,则该字节数为零 (0)。

我的猜测是,实际上,没有抛出异常并且线程没有被中止 - 但它只是永远循环。如果您在调试器中单步执行,您应该能够看到这一点。无论发生什么,你的“快乐”终止条件永远不会被击中......

于 2012-05-10T06:02:45.323 回答
3

由于您正在尝试从流中读取 ASCII 字符,因此请查看以下可能更简单的方法:

public IEnumerable<string> ReadLines(Stream stream)
{
    using (StreamReader reader = new StreamReader(stream, Encoding.ASCII))
    {
        while (!reader.EndOfStream)
            yield return reader.ReadLine();
    }
}

虽然这可能不是您想要的,但要点是:

  • 用aStreamReader为你做所有辛苦的工作
  • 使用 while 循环!reader.EndOfStream来循环流
  • reader.Read(buffer, 0, 1024)如果您希望将块读入缓冲区并附加到结果中,您仍然可以使用。请注意,这些将是char[]块而不是byte[]块,这可能是您想要的。
于 2012-05-10T06:12:43.300 回答
1

在我看来,它只是在阻塞- 即在流结束时等待。要让它返回一个非正数,必须关闭流,即调用者不仅发送了数据,而且关闭了他们的出站套接字。否则,系统无法区分“等待数据包到达”和“流结束”。

如果调用者只发送一条消息,他们应该在发送后关闭他们的出站套接字(他们可以保持他们的入站套接字打开以进行回复)。

如果调用者发送多条消息,那么您必须使用框架方法来读取各个子消息。对于基于文本的协议,这通常意味着“寻找换行符”。

于 2012-05-10T06:11:52.663 回答