0

Python のサーバー ソフトウェアとして Modbus over TCP を実装しました。アプリはマルチスレッド化されており、標準ライブラリに大きく依存しています。サーバー側での接続の管理に問題があります。一方、クライアントとしての Modbus over TCP としての私の実装は問題なく動作します。

実装の説明

  • サーバーはマルチスレッドで、1 つのスレッドがフレーム受信用の SOCK_STREAM ソケットを管理します。
  • select は効率上の理由から使用されます
  • セマフォは、送受信中にソケット リソースへの同時アクセスを防止するために使用されます。
  • Modbus 上位層のカプセル化は、送信メソッドと受信メソッドを介して透過的に行われます。とにかく、正しいヘッダーとペイロードを使用してフレームを構築するだけです...
  • 別のスレッドが実行され、その中で Modbus の送信および受信メソッドが呼び出されます。

TCP コンテキスト

TCP が稼働中で、ポートにバインドされ、最大クライアントが設定され、リッスンしています。

Wireshark ショーの下のトレース:

  • 依頼人:シン
  • 私のアプリ サーバー: SYN、ACK
  • クライアント: ACK

サーバー側では、まったく新しいソケットが期待どおりに作成され、クライアント ソケットにバインドされています。

これまでのところ、すべて問題ありません。

Modbus コンテキスト

  • クライアント: Modbus フレームを送信、TCP フラグ = ACK + PUSH である 0x18
  • 私のアプリ サーバー:待機せず、単一の空の TCP ack フレームを送信します
  • クライアント: 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回答は、それを無効にする方法を示しています。TCP遅延ACKを無効にします。それからそれを有効にする方法を理解するのは簡単なはずです。データを受信した後は、常に再度有効にする必要があることに注意してください。

于 2012-03-14T15:30:17.093 に答える