7

異常な状況が発生しました。TCP実装が部分的に壊れている組み込みシステムと通信する必要がある組み込み状況(Intelボックス、現在2.6.20カーネルを使用)でLinuxシステムを使用しています。私が今知る限り、彼らは私たちからの各メッセージが別々のイーサネットフレームで届くことを期待しています!メッセージがイーサネットフレームに分割されると、問題が発生するようです。

私たちはデバイスとローカルネットワーク上にあり、私たちの間にルーターはありません(スイッチだけです)。

もちろん、私たちは彼らに彼らのシステムを修正するように強制しようとしていますが、それは実現可能ではないかもしれません。

ソケットにTCP_NODELAYを設定しました(接続します)が、一度に複数のメッセージを送信しようとしない場合にのみ役立ちます。複数の送信メッセージが連続している場合、それらのメッセージは1つまたは2つのイーサネットフレームで終わる傾向があり、他のシステムで問題が発生します。

通常、タイマーを使用してメッセージを近づけすぎないようにすることで問題を回避できますが、それによってスループットが明らかに制限されます。さらに、時間を短くしすぎると、ネットワークの輻輳がパケット送信を保留し、複数のメッセージを同じパケットに入れてしまうリスクがあります。

ドライバーにデータがキューに入れられているかどうかを確認する方法はありますか?ドライバーに独立したトランスポート層パケットで独立した書き込み呼び出しを送信させる方法はありますか?socket(7)とtcp(7)のマニュアルページを調べましたが、何も見つかりませんでした。何を探しているのかわからないのかもしれません。

明らかに、UDPは一方通行ですが、繰り返しになりますが、現時点では、もう一方の端に大きな変更を加えることはできないと思います。

どんな助けでも大歓迎です。

4

6 に答える 6

11

IIUC、TCP_NODELAY オプションを設定すると、すべてのパケットがフラッシュされます (つまり、tcp.c は tcp_push_pending_frames への呼び出しで NODELAY の設定を実装します)。そのため、send 呼び出しのたびに socket オプションを設定すると、必要なものが得られるはずです。

于 2008-11-03T15:07:49.313 に答える
2

問題の内容がはっきりしない限り、問題を回避することはできません。

recv() が正確に 1 つのメッセージを受信すると仮定するという初心者の間違いを犯した場合、それを完全に解決する方法はわかりません。イーサネット フレームごとに 1 つのメッセージのみを送信することは 1 つのことですが、受信者が recv() を呼び出す前に複数のイーサネット フレームが到着した場合でも、1 回の呼び出しで複数のメッセージを取得します。

ネットワークの輻輳により、recv() を呼び出す頻度がわかったとしても、(適切なスループットを維持しながら) これを防ぐことは事実上不可能になります。

于 2008-11-05T10:21:48.983 に答える
1

おそらく、TCP_NODELAY を設定し、MTU を十分に低く設定して、フレームごとに最大で 1 つのメッセージが存在するようにしますか? ああ、発信パケットに「dont-fragment」フラグを追加します

于 2008-11-03T16:28:30.227 に答える
0

最悪のシナリオでは、送信されるパケットをより適切に制御できる 1 つ下のレベル (生のソケット) に移動できますが、TCP のすべての核心に対処する必要があります。

于 2008-11-03T16:45:04.923 に答える
0

メッセージごとに新しいソケットを開き、すぐに閉じてみましたか? オーバーヘッドは吐き気を催すかもしれませんが、これでメッセージが区切られるはずです。

于 2008-11-03T16:35:23.303 に答える
-1

たぶん、tcp スタックを低遅延モードにしてみてください:

echo 1 > /proc/sys/net/ipv4/tcp_low_latency

これは、データを結合するよりも、できるだけ早くパケットを送信することを優先するはずです。詳細については、tcp(7) のマニュアルを参照してください。

于 2008-11-03T18:33:20.773 に答える