【问题标题】:Delphi with Indy 10 - Best approach for TCP communicationDelphi with Indy 10 - TCP 通信的最佳方法
【发布时间】:2015-07-30 08:52:54
【问题描述】:

我正在使用 Delphi XE3 和 Indy 10(idTCPServer 和 idTCPClient)创建一个客户端-服务器应用程序。

服务器端将显示所有连接的客户端,我可以在列表中选择一些客户端并向它们发送命令或流/文件。为此,我按照 Remy Lebeau 先生的建议创建了一个消息队列。这是我正在做的事情:

我想知道的是:

  1. 对于我正在尝试做的事情,这是一个好方法吗?

  2. 当一侧开始读/写时,它期望另一侧写/读?如果对方做不到怎么办?假设 SERVER 请求一个文件,但它不存在,CLIENT 是否必须写一个“空”流以避免问题?

顺便说一句,我找不到任何好的例子(Indy 10 TCP 通信),使用队列、错误处理等。在 Indy 的网站上有很多断开的链接。你能给我推荐一个有很好例子的网站吗?

感谢您的帮助!

【问题讨论】:

  • 不使用现有协议(例如 HTTP 或 WebSockets)的原因是什么
  • @mjn,我是这种编程的新手。经过一番研究,Indy 和 TCP 似乎是最好的工具和协议。顺便说一句,服务器和客户端在同一个局域网上......
  • OT:我仍然想知道为什么人们将字符串用于 TCP 远程命令。为什么不只是整数?他们害怕Low(Integer)..High(Integer) 的范围还是为什么会这样?我能想到的唯一原因是可读性,但这是你(或潜在的攻击者)不一定需要的。字符串在接收方更难处理,恕我直言,纯粹是浪费带宽。 [我说的是命令,而不是它们的参数]
  • @TLama,字符串命令包括要发送的文件的路径等参数。但也许我对这个主题的了解不足以理解你的观点......
  • @TLama 事实上,当我第一次开始时,我创建了一个 TCP 客户端/服务器包装器(使用 ScktComp),其中包含预定义的命令列表(在 TCollection 中)。尽管每个可能的命令和参数都有一个唯一的名称,但实际的传输使用了一个唯一的 ID - 并在此之上进行了加密。

标签: delphi tcp indy


【解决方案1】:

当一侧开始读/写时,它期望另一侧写/读?如果对方做不到怎么办?假设 SERVER 请求一个文件,但它不存在,CLIENT 是否必须写一个“空”流以避免问题?

让客户端在传输文件之前发送一个接受/拒绝请求的回复。还要让接收方在传输完成后发送回复,以便发送方知道接收方是否收到了整个文件。

Server: I will send a file
Client: OK
Server: FileStream
Client: OK

Server: Send me a file
Client: OK
Client: FileStream
Server: OK

Server: I will send a file
Client: Not Ready

Server: Send me a file
Client: Not Found

Server: Send me a file
Client: OK
Client: FileStream (error midway)
Server: FAILED

话虽如此,由于您的服务器是向客户端发送命令的服务器,因此请考虑在客户端使用TIdCmdTCPClient 而不是TIdTCPClient。这将为您提供一个专用线程来接收服务器命令,您可以为您的命令创建OnCommand 处理程序并使用提供的TIdCommand 对象来发送回复。

考虑使用TIdTCPConnection.SendCmd() 方法发送命令并读取其初始响应,并使用TIdTCPConnection.GetResponse() 读取最终响应。

【讨论】:

  • 谢谢 Remy Lebeau 先生,我会按照您的提示进行操作的!顺便说一句,如果客户端还需要向服务器发送命令怎么办?我可以使用 TIdCmdTCPServer 和 TIdCmdTCPClient 吗?
  • TIdCmdTCPClientTIdCmdTCPServer 不能很好地协同工作,因为它们都被设计为读取组件,因此它们会相互死锁/冲突。如果您需要双向发送命令,请坚持使用TIdTCPClientTIdTCPServer。但是,您的协议设计确实存在需要注意的竞争条件 - 如果客户端和服务器同时同时相互发送命令会发生什么?通过能够区分重叠的命令和响应,可能通过使用成帧/多路复用,确保您设计的协议能够解决这个问题。
  • 好的,再次感谢您!请让我知道是否有一些地方可以找到有关此的示例。
  • 嗨,雷米·勒博先生。抱歉再次打开这个帖子,如果需要我可以创建一个新的。好吧,您认为如果我使用 TIdCmdTCPClient(接收服务器命令)和 TIdTCPClient(向服务器发送命令)将是避免并发通信问题的好方法吗?每个都将在不同的端口工作。谢谢!
  • 如果可以避免的话,尽量不要使用多个端口。这使网络/防火墙管理员更难管理。此外,您可以使用TIdCmdTCPClient 发送命令,您只需将您的协议设计为异步的(发送命令,不要等待回复,回复到达时单独处理)并将回复格式化为这样CommandHandlers 可以处理的一种方式。由于 TCP 是双向的,您可以随时使用TIdCmdTCPClient 发送出站数据,但由于它使用内部读取线程,该线程将接收所有入站数据。
猜你喜欢
  • 2012-08-04
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
  • 2012-09-06
  • 1970-01-01
  • 2017-03-03
相关资源
最近更新 更多