【问题标题】:Waiting for certain information in a NetworkStream object等待 NetworkStream 对象中的某些信息
【发布时间】:2015-09-29 17:05:59
【问题描述】:

过去几天我一直在尝试使用 BeginRead 和 Read 方法从 NetworkStream 对象中读取数据,但是这两种方法都给我带来了困难并且似乎都不可靠

第一个,“读取”要求我让线程休眠,并期望在休眠完成时出现正确的数据。 像这样:

cmd = System.Text.Encoding.ASCII.GetBytes(CommandString + "\r");
ns.Write(cmd, 0, cmd.Length);
Thread.Sleep(5000);
int _bytes = ns.Read(output, 0, output.Length);
responseOutput = System.Text.Encoding.ASCII.GetString(output, 0, _bytes);
Console.Write(responseOutput);

这在 80% 的时间里都有效,因为服务器的延迟在一天中波动,我也尝试了以下我觉得构造不佳的方法,什么是最有效的轮询数据的方法匹配一组既不烧CPU也不浪费时间的条件?

bool connection_check = false;
String[] new_connection_array = new String[] { "processed successfully", "invalid", "Command not recognised. Check validity and spelling" };

do
{
    int view_bytes = ns.Read(output, 0, output.Length);
    responseOutput += System.Text.Encoding.ASCII.GetString(output, 0, view_bytes);

    foreach (String s in new_connection_array)
         if (responseOutput.IndexOf(s) > -1)
             connection_check = true;

} while (connection_check == false);

提前致谢

编辑:

 public bool SendCommandAndWait(Byte[] command, Regex condition)
        {
            if (callback == null)
            {
                SendCommand(command);

                callback = ar =>
                {
                    int bytesEnd = ns.EndRead(ar);
                    int bytes = bytesEnd;

                    // Process response
                    responseOutput += System.Text.Encoding.ASCII.GetString(output, 0, bytes);

                    // Check if we can return
                    if (condition.IsMatch(responseOutput))
                        return; // Yes, there is a match... return from the async call
                    else // No match, so loop again
                        ns.BeginRead(output, 0, output.Length, callback, null); // Call the loop again
                };
                ns.BeginRead(output, 0, output.Length, callback, null);
            }

            // Because the callback is fired into a different thread and the program continues, we need to loop here so the program doesn't continue without us
            do
            {
                Thread.Sleep(1000);
                //Console.WriteLine(responseOutput);
            } while (!condition.IsMatch(responseOutput));

            if (condition.IsMatch(responseOutput))
            {
                callback = null;
                return true;
            }
            else
                return false;

        }

【问题讨论】:

  • 每天都会问这个问题。 TCP 套接字提供数据流,而不是消息。您不需要 Thread.Sleep(),您需要一个应用程序协议来确定消息边界,以便您知道何时收到完整的消息。如果您没有非常令人信服的理由,请不要使用套接字,请使用更高级别的概念,例如通过 WCF 进行 SOAP。
  • 我知道它们不像消息那样工作,这就是为什么我在数据匹配条件之前“收集”流,但是这个程序将无头运行,作为服务一台服务器,并将联系一个我无法控制的 Telnet 客户端。 Afaik,使用 Sockets 是唯一的出路,更不用说巨大的设计改变不在卡片上
  • @CodeCaster,然后创建或查找可用作目标的问题,将它们作为重复项关闭。我认为每个平台都需要一个问题,以便提供好的示例代码。
  • @Ian 仅针对 C# 就有数百甚至数千个关于这个主题的问题。我找不到合适的规范副本,现在也懒得写。

标签: c# .net sockets networkstream


【解决方案1】:

BeginRead 将允许您定义一个在 beginread 完成时执行的操作。请注意,这与您已阅读所有要阅读的内容时不同。这就是为什么 read 返回读取的字节数。如果您希望读取 20 个字节并获得 10 个字节,那么您将需要再读取 10 个字节。

来自https://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.beginread(v=vs.110).aspx

BeginRead 方法读取尽可能多的可用数据,最多为 size 参数指定的字节数。

如果您希望在调用 BeginRead 方法后阻塞原始线程,请使用 WaitOne 方法。

【讨论】:

  • 嗨 Vegahyo,我已经尝试使用 BeginRead 方法(参见编辑),但回调并不总是在指定的条件下返回,有什么想法吗?谢谢
  • 你需要等待它。但请记住,读取并不总是读取您希望它读取的字节数,您需要检查读取的字节数是否等于您的预期。伪代码:public static ManualResetEvent allDone = new ManualResetEvent(false); BeginRead(blah,blah,blah,callback) allDone.WaitOne();无效回调() { allDone.Set(); }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多