【问题标题】:How to tell when the Stream is at it's end?如何判断 Stream 何时结束?
【发布时间】:2013-08-16 14:35:38
【问题描述】:

如何在不使用 BinaryWriter/Reader 的情况下将 TCP 流的大小嵌入或告知接收方?

必须有一种快速的方法让它知道它是否已经到达终点,当然,除了终止连接。

tcp.GetStream().Write(ms.GetBuffer(), 0, (int)ms.Length);

我是这样发送的,但接收是困难的部分。

编辑:

这对我不起作用:

                while (tt1.GetStream().DataAvailable)
                {
                    su = Image.FromStream(tt1.GetStream());
                }

【问题讨论】:

  • 为什么需要先得到长度才能阅读?
  • 在调用.DataAvailableImage.FromStream 之前,您是否尝试将tt1.GetStream() 放入临时的NetworkStream 或任何类型的流中?另外,我不认为 Image.FromStream 需要在一个 while 循环中 - 它应该处理到达流本身的末尾。
  • 好的,会尝试,意思是,在while循环中将其复制到NetworkStream,并在while循环之后读取。
  • 我的意思是只使用 Image.FromStream(tt1.GetStream()); 在不检查 DataAvailable 的情况下,这在任何循环之外都不起作用吗?
  • 哦,不,它没有。除了,如果我断开连接,那么它适用于 1 张图片。 (它不知道结束,所以即使没有数据它也会继续读取,所以如果我断开连接,它会强制读取它)。否则它将是完美的,因为我可以直接从流中读取。或者等待它不起作用,即使我在循环之外断开连接。

标签: c# tcp stream


【解决方案1】:

不,没有办法(快或慢)来判断您何时到达网络流的末尾。 DataAvailable 会告诉您当前是否有数据可用,但它不能告诉您是否有更多的数据流下来。

据我所知,有两种可靠的方法可以确定您是否已到达网络流的末尾:

  1. 让发送方将长度(int 或 long)作为流的前 4(或 8)个字节发送。接收器读取此长度,然后继续读取流,直到读取到那么多字节。
  2. 同意“流结束”标记。这可以采取多种形式。例如,对于仅包含 ASCII 字符串的简单流,您可以同意字节值 255 表示字符串结束。或者您可以使用 ASCII EOT 字符。对于面向记录的字符串,记录的第一个字节可以是记录类型,记录类型 0xFF 可能表示“记录结束”。

换句话说,网络流无法知道何时结束。不像文件流可以。您必须在数据中编码流长度或流标记的结尾。

更新

System.Drawing.Image.FromStream 的文档说:

如果这个方法被同一个流连续调用,则流被重置为零。

因此您不能使用该方法从同一流中读取多个图像。

我怀疑您需要做的是更改您的数据,使其结构如下:

length | data for image 1 | length | data for image 2 | 0

然后您将读取长度,将那么多字节读入一个字节数组,并从该字节数组创建图像(可能通过在其周围包装内存流),然后读取下一个长度,下一个字节块等,直到您读取到长度为 0,这表示流的结束。

【讨论】:

  • 好的,但在第一个示例中。我如何在 Stream 中实现它?我目前使用 BinaryWriter 有这样的方法,但我不希望使用包装器而只使用流(尽可能低级别)。
【解决方案2】:

您可以使用接收器中的 .DataAvailable 属性来确定要读取的流中是否还有可用的数据,但 Length 属性本身并没有实现。

使用

do {
    ...
    myNetworkStream.Read(buffer, 0, someSizeToCopyEachLoop)
}
while(myNetworkStream.DataAvailable);

如果您确实需要流的长度,您可以将其内容复制到 MemoryStream 并读取其 .Length 属性:

MemoryStream s = new MemoryStream();
myNetworkStream.CopyTo(s);
int length = s.Length;

【讨论】:

  • 我试过了,但我有另一个 while 循环,它似乎会导致冲突,因为该 while 循环将比 DataAvailable 更快/更慢,这意味着它可能会在它的时候得到 false/true实际上并非如此。好的,对我来说根本不起作用,即使我尝试只将其用作 While 参数;S
  • 我发送的东西在内存流中,所以当我发送它时,我可以轻松发送正确数量的数据:tcp.GetStream().Write(ms.GetBuffer(), 0 , (int)ms.Length); , 但是,接收部分不知道什么时候完成。
  • 我建议你将传入的 TCP 流复制到一个新的 MemoryStream 中,你可以读取它的长度。
  • 哦,但是想尝试防止这种情况发生,因为它会减慢速度。我试图能够直接从网络流中读取(它是一个图像,所以 Image.FromStream),如果我断开连接,它可以工作,但那是因为我强制它读取流,即使它不是完成。
  • 我发表了评论作为对您原始帖子的回复。如果我们在这里制作太多 cmets,我们也可以将其移至讨论或其他内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
相关资源
最近更新 更多