1

複数のクライアント接続を受け入れる単純な TCP リレーを構築しようとしています。

Client1 --> TCPrelay1 --> RealServer1 --> TCPrelay1 --> Client1
Client2 --> TCPrelay1 --> RealServer1 --> TCPrelay1 --> Client2
Client3 --> TCPrelay1 --> RealServer1 --> TCPrelay1 --> Client3

その件で何か。クライアント数に制限なし


ここで UDP リレー スクリプトを見つけました。

TCPに変更しようとしました。私はPythonソケットに本当に慣れていません。では、私のコードの何が問題になっているのでしょうか? 何も起こっていません。そして、それは中継していません。

#SOCK_STREAM --TCP
localPort = 5000
remotePort = 5000

#SV
remoteHost = "xxxxx"

try:
    localPort = int(localPort)
except:
    fail('Invalid port number: ' + str(localPort))
try:
    remotePort = int(remotePort)
except:
    fail('Invalid port number: ' + str(remotePort))

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', localPort))
    s.listen(1)
except:
    fail('Failed to bind on port ' + str(localPort))

knownClient = None

while True:
    conn, addr = s.accept()
    conn2, addr2 = s.connect((remoteHost, remotePort))
    data = connection.recv(1024)
    if knownClient is None:
        knownClient = addr
    if addr == knownClient:
        s.sendall(data)
        print "Sent     : " + ":".join("{0:X}".format(ord(c)) for c in data)
    else:   
        s.sendall(data)
        print "Received : " + ":".join("{0:X}".format(ord(c)) for c in data)

[無視]
いくつかの調査を行い、別のSOの質問でこのロジックを見つけました:

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))

しかし、私はまだそれを実装する方法を理解しようとしています。

4

1 に答える 1

1

コードは 1 つの接続を受け入れてから、1 つのデータ ブロックを一方向に中継し、その接続を二度と調べません。

コードの 2 番目のチャンクにはさまざまな問題がありますが、大きな問題は、デッドロックが発生する可能性があることです。への呼び出し中に、 への送信が完了するまで がデータの読み取りを拒否したB.sendall場合、これは中継しているプロトコルでは合法である可能性があります。から送信完了まで。BABB

適切なリレーは、一度に 4 つのことを実行しようとする必要があり、1 つのことが完了するのを待ってから別のことを開始することはできません。これらの 4 つのことは次のとおりです。

1) 接続 A から読み取ります。(大量のデータが既にバックアップされている場合を除きます。)

2) 接続 B から読み取ります。(大量のデータが既にバックアップされている場合を除きます。)

3) 接続 A に書き込みます。(接続 B から受信した未中継のデータがない場合を除きます。)

4) 接続 B に書き込みます (接続 A から受信した未中継のデータがない場合を除く)。

特に、各方向の未送信データ用に 1 つずつ、計2 つのバッファーが必要です。ノードの 1 つがデータを受信するのを待つ必要があり、そのノードがデータを受信するのを待っているとデッドロックになる可能性があるため、方向を変えることはできませ

一般に、プロキシを実装する最も簡単な方法は、接続ごとに 2 つのスレッド (各方向に 1 つずつ) を使用することです。

于 2013-04-21T14:23:29.770 に答える