【问题标题】:Use TIdCmdTCPServer for binary data?将 TIdCmdTCPServer 用于二进制数据?
【发布时间】:2018-11-25 04:21:36
【问题描述】:
我的 Windows 应用程序中有一个基于 TIdCmdTCPServer 的 TCP 服务器,它的性能非常好。现在我有一个不发送文本字符串而是发送二进制数据的设备。我真的不想重写我的工作代码来使用TIdTCPServer。
有什么方法可以使用我当前的代码并在某处获取丢弃的数据,即我可以访问接收到的原始数据而不干扰使用文本的其他连接吗?
我尝试了OnBeforeCommandHandler 事件,但它似乎已经假定数据是一个字符串(即在第一个零字节处截断)。
【问题讨论】:
标签:
c++
c++builder
indy
indy10
【解决方案1】:
TIdCmdTCPServer 不会像您声称的那样停止读取 nul 字节。默认情况下,它通过调用TIdIOHandler.ReadLn() 读取每个命令,直到收到(CR+)LF。但是,TIdIOHandler.DefStringEncoding 默认设置为 US-ASCII,因此在将二进制数据作为字符串读取时可能会导致数据丢失。
话虽如此,TIdCmdTCPServer 主要是为文本命令设计的。默认情况下,tt 无法接收二进制命令或二进制参数。但是,如果二进制数据遵循文本命令,您的TIdCommandHandler.OnCommand 事件处理程序可以在收到命令后读取二进制数据,只需根据需要使用ASender.Context.Connection.IOHandler 读取二进制文件即可。
否则,如果这不符合您的需要(因为二进制命令不是通常会触发OnCommand 事件的格式),您将不得不从TIdCmdTCPServer 派生一个新类并拥有它:
覆盖虚拟ReadCommandLine() 方法以从Connection 读取二进制命令及其参数,并以您选择的string 格式返回该数据(您可以使用Indy 的IndyTextEncoding_8bit 编码,或BytesToStringRaw() 函数,以帮助您,或使用您想要的任何 string 格式)。然后定义一个CommandHandler 来匹配那个字符串化的命令。
覆盖虚拟DoExecute() 方法,然后您可以完全控制Connection 的读取,并且可以根据需要处理命令。要触发OnCommand 事件,请调用服务器的CommandHandlers.HandleCommand() 方法,将您选择的string 值传递给它。
就个人而言,我不建议在同一台服务器上混合使用文本和非文本客户端。它们显然使用不同的协议,因此您应该在不同的端口上使用不同的服务器来分别处理它们。