2013-11-15 2 views
0

Недавно я сделал первый удар в Twisted/Python, создав приложение, которое перекликает входящие строки UDP из TCP-порта. Я предположил, что это будет очень просто, но я не смог заставить его работать. Ниже приведен код, приведенный ниже в примере TCP & UDP-сервер, измененный для совместной работы. Я просто пытаюсь передать некоторые данные между ними. Любая помощь будет оценена по достоинству.Twisted UDP to TCP Bridge

from twisted.internet.protocol import Protocol, Factory, DatagramProtocol 
from twisted.internet import reactor 

class TCPServer(Protocol): 

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


class UDPServer(DatagramProtocol): 

    def datagramReceived(self, datagram, address): 
     #This is where I would like the TCPServer's dataReceived method run passing "datagram". I've tried: 
     TCPServer.dataReceived(datagram) 
     #But of course that is not the correct call because UDPServer doesn't recognize "dataReceived" 


def main(): 
    f = Factory() 
    f.protocol = TCPServer 
    reactor.listenTCP(8000, f) 
    reactor.listenUDP(8000, UDPServer()) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

ответ

2

Это, по существу, часто задаваемые How do I make input on one connection result in output on another?

< УДП - специфика> TCP в этом вопросе не нарушают общий ответ, данный в записи FAQ. Просто обратите внимание, что с DatagramProtocol проще работать, чем с Protocol, потому что у вас уже есть экземпляр DatagramProtocol, без необходимости сотрудничать с фабрикой, как и в случае с Protocol.

Другими словами:

from twisted.internet.protocol import Protocol, Factory, DatagramProtocol 
from twisted.internet import reactor 

class TCPServer(Protocol): 
    def connectionMade(self): 
     self.port = reactor.listenUDP(8000, UDPServer(self)) 

    def connectionLost(self, reason): 
     self.port.stopListening() 


class UDPServer(DatagramProtocol): 
    def __init__(self, stream): 
     self.stream = stream 

    def datagramReceived(self, datagram, address): 
     self.stream.transport.write(datagram) 


def main(): 
    f = Factory() 
    f.protocol = TCPServer 
    reactor.listenTCP(8000, f) 
    reactor.run() 

if __name__ == '__main__': 
    main() 

Обратите внимание на существенное изменение: UDPServer необходимо вызвать метод на примере TCPServer поэтому необходима ссылка на этот экземпляр. Это достигается тем, что экземпляр TCPServer передает себя в инициализатор UDPServer, а инициализатор UDPServer сохраняет эту ссылку как атрибут экземпляра UDPServer.

+0

Я уже рассматривал этот пример, но я понимаю, что DatagramProtocol не может/не использует фабрику. Когда я попытался решить это, как в примере, которым вы поделились, я получил ошибки, которые UDPServer не любил ссылаться на общую фабрику. С другой стороны UDP разрывает пример «одно соединение, вывод на другой». – SaranWrap