0

我已经在 Python 中实现了一个基于 TCP 的 Modbus 作为服务器软件。应用程序是多线程的,并且严重依赖标准库。我在管理服务器端的连接时遇到问题。同时,我作为客户端的 Modbus over TCP 实现工作得很好。

实现说明

  • 服务器是多线程的,一个线程管理 SOCK_STREAM 套接字用于接收帧
  • 出于效率原因使用 select
  • 信号量用于防止在发送或接收时对套接字资源的并发访问
  • Modbus上层的封装是通过发送和接收方法透明地完成的,无论如何只是构建一个带有正确的头和有效载荷的帧......
  • 另一个线程运行,在其中调用 Modbus 发送和接收方法。

TCP 上下文

TCP 启动并运行,绑定到一个端口,最大客户端设置和侦听。

wireshark 下的痕迹显示:

  • 客户:SYN
  • 我的应用服务器:SYN、ACK
  • 客户:ACK

在服务器端,一个全新的套接字已按预期创建并绑定到客户端套接字。

到目前为止,一切都很好。

Modbus 上下文

  • 客户端:发送 Modbus 帧,TCP 标志 = 0x18,即 ACK + PUSH
  • 我的应用服务器:不等待并发送一个空 TCP 确认帧
  • 客户端:等待带有 tcp ack 标志的 modbus 帧。因此,将其视为错误并要求关闭连接。

因此,我的服务器软件之后无法发送任何实际响应,因为客户端的套接字正在关闭或已经关闭。

我的问题

  • 我收到一个主线程需要处理的 modbus 帧(服务器端)
  • 处理需要几毫秒,同时通过我的服务器套接字发送一个 TCP ACK 帧,而我希望它不发送任何东西!

您对如何管理 ACK 行为有任何想法吗?我已经阅读了有关 naggle 算法的内容,但它似乎不在问题的范围内……我不确定 setsockopt 方法的任何选项也能解决我的问题,但我可能弄错了。

如果您有任何建议,我很感兴趣......我希望我足够清楚。

4

1 回答 1

0

所有 TCP 数据包都必须包含有效负载似乎是一个奇怪的要求,因为除非您与 TCP 堆栈集成,否则这很难控制。如果确实是由于 ACK 没有 Modbus 有效负载而导致客户端崩溃的情况,我认为您可以从 python 中做的唯一事情是尝试禁用 TCP_QUICKACK 套接字选项,以便 TCP 在发送 ACK 之前等待 500 毫秒。这显然不适用于所有情况(或者如果您的代码需要> 500ms 来创建响应,则可能根本不起作用),但我不知道使用 python 的套接字 API 的任何其他选项。

这个 SO 答案告诉您如何禁用它:Disable TCP Delayed ACKs。应该很容易弄清楚如何从中启用它。请注意,您需要在收到数据后不断地重新启用它。

于 2012-03-14T15:30:17.093 回答