4

2 つの TCP ソケット間に目に見えないリレーを確立する Python コードを書き込もうとしています。私の現在のテクニックは、2 つのスレッドをセットアップすることです。各スレッドは、特定の方向で一度に 1kb のデータを読み書きします (つまり、A から B に 1 スレッド、B から A に 1 スレッド)。

これは一部のアプリケーションとプロトコルで機能しますが、絶対確実というわけではありません。この Python ベースのリレーを実行すると、特定のアプリケーションが異なる動作をすることがあります。クラッシュするものさえあります。

これは、私がソケット A で読み取りを実行し終えると、そこで実行されているプログラムが、そのデータが既に B に到着したと見なしているからだと思います。 B がデータを受信する準備ができていない (それによってsend()しばらくブロックする) 状況では、A は B にデータを正常に送信したと信じている状態になりましたが、私はまだデータを保持しており、send()呼び出しを待っています。実行します。これが、現在の中継コードを使用しているときに一部のアプリケーションで見つかった動作の違いの原因だと思います。私は何かを見逃しましたか、それとも正しいですか?

もしそうなら、私の本当の質問は: この問題を回避する方法はありますか? B がデータを受信する準備ができていることがわかっている場合にのみ、ソケット A から読み取ることは可能ですか? または、[すでに開いて確立されている] TCPソケット間で真に「見えない」双方向リレーを確立するために使用できる別の手法はありますか?

4

3 に答える 3

5

B がデータを受信する準備ができていることがわかっている場合にのみ、ソケット A から読み取ることは可能ですか?

確かに:ソケット A と B の両方でselect.selectを使用し (一方だけが準備完了であると返された場合は、もう一方のソケットで使用します)、両方の準備が整っていることがわかっている場合にのみ、A から読み取り、B に書き込みます。例えば:

import select

def fromAtoB(A, B):
    r, w = select.select([A], [B], [])
    if not r: select.select([A], [], [])
    elif not w: select.select([], [B], [])
    B.sendall(A.recv(4096))
于 2010-04-09T02:43:18.077 に答える
1

それがあなたの問題である可能性は低いと思います。

一般に、送信側のアプリケーションは、受信側のアプリケーションが実際に recv() を呼び出してデータを読み取るタイミングを知ることができません。送信側の send() は完了している可能性がありますが、送信元と送信先の OS の TCP 実装はバッファリング、フロー制御を行っています。 、再送信など

途中であなたの中継がなくても、Aが「Bにデータが届いているとみなす」には、Bから「うん、わかった」と返事をもらうしかありません。

于 2010-04-09T02:40:39.953 に答える
1

おそらく、プロキシしているアプリケーションの記述が不十分です。

たとえば、私が電話した場合、recv(fd, buf, 4096, 0);4096 バイトは約束されません。システムは、それを提供するために最善を尽くします。

recv1k がアプリケーションまたはサイズの倍数ではなく、sendアプリケーションが破損している場合、送信されたデータを 1k ブロックにグループ化するとアプリが破損します。

于 2010-04-09T17:12:17.980 に答える