由于我的服务器实现的意外答案,Modbus TCP客户端关闭了连接

时间:2012-03-14 13:29:14

标签: python tcp modbus

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

实施说明

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

TCP上下文

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

wireshark下的痕迹显示:

  • 客户:SYN
  • 我的应用服务器:SYN,ACK
  • 客户:确认

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

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

Modbus上下文

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

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

我的问题

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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