【问题标题】:Indy TCPClient and rogue byte in InputBufferIndy TCPClient 和 InputBuffer 中的恶意字节
【发布时间】:2012-03-24 16:28:47
【问题描述】:

我正在使用以下几行代码通过 IP 从外部调制解调器/路由器(又名设备)写入和读取。

TCPClient.IOHandler.Write(MsgStr);
TCPClient.IOHandler.InputBuffer.Clear; 
TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

MsgStr 是一个字符串类型,其中包含我要发送到我的设备的文本。 缓冲区被声明为 TIdBytes。 我可以确认 IOHandler.InputBufferIsEmpty 在调用 ReadBytes 之前立即返回 True。

我希望收到的前 10 个字节非常具体,因此从我的角度来看,我只对发送字符串后收到的前 10 个字节感兴趣。

我遇到的问题是,在与某些设备通信时,在建立连接后我第一次发送字符串时返回的第一个字节在我的缓冲区中放置了一个流氓(随机)字节输出。后面的字节都是正确的。

例如,我期望的 10 个字节可能是:#6A1EF1090#3,但我得到的是 .#6A1EF1090。在这个例子中,我有一个不应该有的句号。

如果我再次尝试发送,它工作正常。 (即建立连接后发送的第二次写入)。 (对我来说)奇怪的是使用 Socket Sniffer 不会显示返回的随机字节。如果我创建自己的“服务器”来接收响应并发送回一些东西,那么它 100% 的时间都可以正常工作。其他软件 - 即不是我的软件 - 与设备通信良好(但我当然不知道他们如何解析数据)。

上面有什么我做错的事情会导致这种情况 - 请记住,它只发生在我在建立连接后第一次使用 Write 时?

谢谢

编辑

我正在使用 Delphi 7 和 Indy 10.5.8

更新

好的。经过大量测试和寻找,我离找到这个解决方案还差得远。我得到两个主要场景。 1 - 第一个字节丢失,2 - 在接收数据包的开头“引入”字节。使用 TIdLogEvent 和 TIdLogDebug 都可以适当地显示丢失的字节或初始引入的字节。因此,我上面的 ReadBytes 声明始终显示了 Indy 认为存在的内容(在我看来)。

另外,为了进一步测试,我下载并安装了 ICS 组件。不幸的是(或者幸运的是,取决于你如何看待它)这并没有显示出与 Indy 相同的问题。这没有显示第一个字节丢失,也没有显示开头引入的字节。但是,我只进行了表面测试,但 Indy “几乎立即”产生了这种行为,而 ICS 根本没有产生这种行为。

如果有人感兴趣,我可以提供一个小型演示应用程序来说明问题和我连接的 IP - 这是一个公共 IP,因此任何人都可以访问它。否则现在,我只需要解决它。我不愿意切换到 ICS,因为 ICS 在这种情况下可能工作正常,并且考虑到使用这个套接字的东西几乎是程序的全部关键,必须用 ICS 完全替换 Indy 会很讨厌。

【问题讨论】:

  • 尝试发送 AnsiString(sizeof(char)=1),这可能会有所帮助
  • 该代码应该放在哪里?仅供参考,我编辑了我的问题以显示我正在使用的 Delphi 版本,以防你认为我使用的是使用 Unicode 的更高版本的 Delphi。
  • 你应该使用标签来指定delphi版本
  • 你初始化缓冲区并检查是否真的是 ReadBytes 添加了额外的字节?
  • 如果这是一个旧的基于串行端口的设备,那么我的记忆告诉我,你经常会在打开端口时得到一个 duff 字符作为第一个字节。这是界面的本质。如果您可以确定您的数据以 # 开头,则查找它,并忽略之前的任何内容。

标签: delphi tcp delphi-7 indy10


【解决方案1】:

最后一个参数(真)

TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

导致读取追加而不是替换缓冲区内容。

这要求首先正确设置缓冲区的大小和内容。

如果参数为 False,则缓冲区内容将被替换为给定的字节数。

【讨论】:

  • 不幸的是,将其设置为 False 没有任何区别 - 如果这就是您的意思。我还尝试了 SetLength(Buffer,10) 与 True/False 的各种组合,以防万一它没有帮助。但是考虑到 True 对随后的每次发送/接收都有效,如果这有效,我会感到惊讶(尽管很高兴)。 :)
【解决方案2】:

ReadBytes() 不会将恶意字节注入缓冲区,因此鉴于您提供的信息有限,我现在只能想到两种可能性:

  1. 设备确实在初始连接时发送了一个额外的字节,就像 mj2008 建议的那样。如果数据包嗅探器没有检测到它,请尝试将 Indy 自己的 TIdLog... 组件之一附加到您的 TIdTCPClient,例如 TIdLogFileTIdLogEvent,以验证 TIdTCPClient 实际从套接字接收的内容。

  2. 你有另一个线程同时从同一个连接读取,破坏了InputBuffer。即使是对TIdTCPClient.Connected() 的调用也会执行读取。如果您正在使用线程,请不要同时在多个线程中执行读取。

【讨论】:

  • 谢谢。我会尝试 pt 1 看看是否能提供任何见解并报告。
猜你喜欢
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 2021-05-17
  • 2013-07-26
  • 1970-01-01
相关资源
最近更新 更多