2013-03-26 93 views
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() 

現在,一點就是實例不能被包含到全局對象,並且應該把這兩個類中:怎麼了?

回答

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的引用來告訴ServerProtocol使用哪個ClientProtocol。

注意:此代碼中沒有錯誤檢查,因此如果事情出錯(例如,如果真實服務器未在偵聽),您可能會遇到有關NoneType的錯誤。

重要的線路有:

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

在這裏,你傳遞一個參考ServerProtocol到MyClientFactory構造。它將此引用存儲在成員變量中。

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

然後,一旦連接從您的腳本作出了真正服務器,情況相反:讓當客戶端工廠創建一個ClientProtocol,它可以通過在參考你做到這一點。該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) 
+0

是的,我已經想通了,這樣的事情可能是處理它的方式,但我寧願不與構造玩,並添加到客戶工廠的引用。這種方式很容易工作。 然後,關於從客戶端到服務器的引用,我已經添加了一個對象到客戶端,在客戶端添加自己的對象之前是「None」。但是,我的代碼在我的答案。現在我只需要在兩種實現之間進行選擇,你或我的! :) 謝謝你的幫助! – 2013-03-26 18:46:04

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() 
+0

非常好的UO代理。正是我在找什麼。和同一個碎片。 – 2015-04-26 15:08:25