5

我正在使用以下几行代码通过 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 会很讨厌。

4

2 回答 2

3

最后一个参数(真)

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

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

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

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

于 2012-03-07T06:36:31.390 回答
1

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

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

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

于 2012-03-07T11:16:32.553 回答