2

必要なのは、一種の中間者攻撃です。クライアント(さまざまな長さのバイナリデータ)から接続を受信し、接続先のサーバー(クライアントとして機能)にストリームを転送するサーバーが必要です。次に、接続されているサーバーからクライアントにデータを送り返します。

実際には、クライアントとサーバーの間に立って、それらが交換するデータを渡します(これはストリームであるため、一方の側から継続的に取得し、もう一方の側に送信します)。
サーバーは静的であるため、常に同じであり、そのアドレスをハードコーディングすることもできます。ただし、クライアントが接続を切断すると、このサーバーは「実際の」サーバーへの接続も切断する必要があります。

私は周りを見回してきましたが、そのような単純な問題の解決策や例を見つけることができませんでした。

私が作成したコードは実際に機能しますが、「これは割り当てられたクライアントです」というサーバー部分、または「これはあなたのサーバーです」というクライアントへの参照を配置する方法をまだ見つけることができません。これが私のコードです:

#!/usr/bin/env python

from twisted.internet import protocol, reactor
from twisted.protocols import basic

client = None
server = None

class ServerProtocol(protocol.Protocol):
    def connectionMade(self):
        global server
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        server = self
        reactor.connectTCP('localhost', 1324, factory)

    def dataReceived(self, data):
        global client
        client.transport.write(data)

class ClientProtocol(protocol.Protocol):
    def connectionMade(self):
        global client
        # Here's the instance of the client
        client = self

    def dataReceived(self, data):
        global server
        server.transport.write(data)

def main():
    import sys
    from twisted.python import log
    log.startLogging(sys.stdout)
    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol

    # Here's the instance of the server
    server = ServerProtocol

    reactor.listenTCP(2593, factory)
    reactor.run()

if __name__ == '__main__':
    main()

ここで重要なのは、インスタンスをグローバルオブジェクトに含めることはできず、2つのクラス内に配置する必要があるということです。

4

2 に答える 2

4

私は自分で問題を解決することができました。今後の参考のために(またはこの問題を抱えている他の人を助けるために)、これが私が問題を解決するために使用したコードです。

私の解決策とjedwardsによって親切に与えられた解決策の両方が機能すると思います。今、私は自分のやったことが正しいことを確認するためにもう少し勉強する必要があります。これはTwistedフレームワークを使用した最初のアプリケーションであり、他の誰かのソリューションを勉強することは何か新しいことを学ぶ方法です!:)

#!/usr/bin/env python

from twisted.internet import protocol, reactor
from twisted.protocols import basic

class ServerProtocol(protocol.Protocol):
    def __init__(self):
        self.buffer = None
        self.client = None

    def connectionMade(self):
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        factory.server = self

        reactor.connectTCP('gameserver16.gamesnet.it', 2593, factory)

    def dataReceived(self, data):
        if (self.client != None):
            self.client.write(data)
        else:
            self.buffer = data

    def write(self, data):
        self.transport.write(data)
        print 'Server: ' + data.encode('hex')

class ClientProtocol(protocol.Protocol):
    def connectionMade(self):
        self.factory.server.client = self
        self.write(self.factory.server.buffer)
        self.factory.server.buffer = ''

    def dataReceived(self, data):
        self.factory.server.write(data)

    def write(self, data):
        self.transport.write(data)
        print 'Client: ' + data.encode('hex')

def main():
    import sys
    from twisted.python import log

    log.startLogging(sys.stdout)

    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol

    reactor.listenTCP(2593, factory)
    reactor.run()

if __name__ == '__main__':
    main()
于 2013-03-26T18:55:04.567 に答える
3

このアプローチを検討してください

#!/usr/bin/env python

import sys
from twisted.internet import reactor
from twisted.internet.protocol import ServerFactory, ClientFactory, Protocol
from twisted.protocols import basic
from twisted.python import log

LISTEN_PORT = 2593
SERVER_PORT = 1234


class ServerProtocol(Protocol):
    def connectionMade(self):
        reactor.connectTCP('localhost', SERVER_PORT, MyClientFactory(self))

    def dataReceived(self, data):
        self.clientProtocol.transport.write(data)

class ClientProtocol(Protocol):
    def connectionMade(self):
        # Pass ServerProtocol a ref. to ClientProtocol
        self.serverProtocol.clientProtocol = self;  

    def dataReceived(self, data):
        self.serverProtocol.transport.write(data)

class MyServerFactory(ServerFactory):
    protocol = ServerProtocol
    def buildProtocol(self, addr):
        # Create ServerProtocol
        p = ServerFactory.buildProtocol(self, addr)
        return p

class MyClientFactory(ClientFactory):
    protocol = ClientProtocol
    def __init__(self, serverProtocol_):
        self.serverProtocol = serverProtocol_

    def buildProtocol(self, addr):
        # Create ClientProtocol
        p = ClientFactory.buildProtocol(self,addr)
        # Pass ClientProtocol a ref. to ServerProtocol
        p.serverProtocol = self.serverProtocol
        return p

def main():
    log.startLogging(sys.stdout)

    reactor.listenTCP(LISTEN_PORT, MyServerFactory())
    reactor.run()

if __name__ == '__main__':
    main()

ServerProtcolインスタンスは、それ自体の参照をMyClientFactoryコンストラクターに渡します。このコンストラクターは、関連付けられているServerProtocolインスタンスをClientProtcolに通知します。

同様に、ClientProtocol接続が確立されると、ServerProtocolへの参照を使用して、使用するClientProtocolをServerProtocolに通知します。

注:このコードにはエラーチェックがないため、問題が発生した場合(たとえば、実サーバーがリッスンしていない場合)、NoneTypeに関するエラーが発生する可能性があります。

重要な行は次のとおりです。

reactor.connectTCP('localhost', SERVER_PORT, MyClientFactory(self))
#...
def __init__(self, serverProtocol_):
    self.serverProtocol = serverProtocol_

ここでは、ServerProtocolへの参照をMyClientFactoryコンストラクターに渡します。この参照をメンバー変数に格納します。これを行うのは、クライアントファクトリがClientProtocolを作成するときに、参照を次の場所に渡すことができるようにするためです。

# Pass ClientProtocol a ref. to ServerProtocol
p.serverProtocol = self.serverProtocol

次に、スクリプトからサーバーへの接続が確立されると、逆のことが起こります。ClientProtocolは、ServerProtocolにそれ自体への参照を提供します。

# Pass ServerProtocol a ref. to ClientProtocol
self.serverProtocol.clientProtocol = self;

最後に、両方のプロトコルは、相互に保存された参照を使用して、データを受信したときにデータを送信します。

def dataReceived(self, data):
    self.clientProtocol.transport.write(data)
#...
def dataReceived(self, data):
    self.serverProtocol.transport.write(data)
于 2013-03-26T16:36:33.887 に答える