0

通过阅读这里的一些问题和答案,似乎 telnet 流从未真正关闭。使用 DataAvailable() 不会返回。

我继承了一些需要很长时间才能完成的代码,我们认为问题出在 telnet 服务器上。但是,有一个字节[32757],代码试图在其中存储 telnet 服务器的响应。

类似于以下内容:

Byte byteArray[] = new Byte[32757];
TcpClient sock = new TcpClient();
sock.GetStream().read(byteArray, 0 byteArray.length);

如果没有 32757 字节或更多字节,我假设此代码会等待,直到发送足够的空数据包来构成字节数组的大小。这个对吗?

有没有办法检查 telnet 服务器是否已完成发送它想要的所有内容?telnet 会话的每个“页面”中没有可见的终止字符或字符串。

我在想一种更正此代码的方法是一次读取几个字节,将其添加到字符串中,检查字符串中是否存在终止字符或字符集,如果找到则返回。否则,读取更多字节,将其添加到字符串中,然后再次检查。

建议?

4

2 回答 2

4

除了 Jon Skeets 的解释之外,还有一点提示:

由于 telnet 是基于文本(行)的协议,因此读取 byte[] 意味着您必须重新组合文本。使用 TextReader 会更好:

System.IO.TextReader reader = new System.IO.StreamReader(
           sock.GetStream(), Encoding.ASCII);
string line;
while ((line = reader.ReadLine()) != null)  ...;

我在这里猜测 telnet 使用 ASCII。

于 2009-05-01T11:03:20.953 回答
3

不,Stream.Read通常不会等到它读取所有内容,而且对于网络流来说更不可能。它会读取任何可用的数据,或者阻塞直到有一些数据可用,但仅此而已。

服务器“完成”发送将要发送的内容并没有真正的概念,除非:

  • a)它会提前告诉你它将发送多少
  • b)它指示何时完成某种终止数据
  • c) 它关闭连接

您可能希望使用某种计时器来实现“继续阅读,直到其中一个读取时间超过 5 秒”的效果。请注意,读取仍然会发生 - 您只需选择那个时间来更新 UI(或其他)。这是一个相当棘手的话题,你真的需要非常清楚自己(和文档!)你想要做什么,以及哪个线程将处理什么。

另一种方法是在 上设置读取超时TcpClient,但我没有这方面的经验。您可能只需要在阅读时使用TcpClient.ReceiveTimeout然后IOException适当地处理结果,但我对此没有任何建议。

于 2009-05-01T10:52:47.360 回答