2013-03-26 96 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