Twisted server-client data sharing

笑着哭i 提交于 2019-11-27 15:21:21

问题


I slightly modified a server-client Twisted program on this site, which provided a program that could act as a server and a client (http://stackoverflow.com/questions/3275004/how-to-write-a-twisted-server-that-is-also-a-client). I am able to connect the server-client to an external client on one side and an external server on the other. I want to transfer data from the external client to the external server via the server-client program. The problem I am having is getting the line received in the ServerProtocol class (in the server-client program) into the ClientProtocol class (in the server-client program). I have tried a number of ways of doing this, including trying to use the factory reference, as you can see from the def init but I cannot get it to work. (at the moment I am just sending literals back and forth to the external server and client) Here is the server-client code:

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


class ServerProtocol(basic.LineReceiver):        
    def lineReceived(self, line):
        print "line recveived on server-client",line
        self.sendLine("Back at you from server-client")
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        reactor.connectTCP('localhost', 1234, factory)

class ClientProtocol(basic.LineReceiver):
    def __init__(self, factory):
        self.factory = factory

    def connectionMade(self):
        self.sendLine("Hello from server-client!")
        #self.transport.loseConnection()

    def lineReceived(self, line):
        print "line recveived on server-client1.py",line
        #self.transport.loseConnection()

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

    log.startLogging(sys.stdout)
    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol
    reactor.listenTCP(4321, factory)
    reactor.run()

if __name__ == '__main__':
    main()

I should mention that I am able to connect to the server-client program with the external server and external client on ports 4321 and 1234 respectively and they just echo back. Also, I have not shown my many attempts to use the self.factory reference. Any advice or suggestions will be much appreciated.


回答1:


This question is very similar to a popular one from the Twisted FAQ:

How do I make input on one connection result in output on another?

It doesn't make any significant difference that the FAQ item is talking about many client connections to one server, as opposed to your question about one incoming client connection and one outgoing client connection. The way you share data between different connections is the same.

The essential take-away from that FAQ item is that basically anything you want to do involves a method call of some sort, and method calls in Twisted are the same as method calls in any other Python program. All you need is to have a reference to the right object to call the method on. So, for example, adapting your code:

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

class ServerProtocol(basic.LineReceiver):        
    def lineReceived(self, line):
        self._received = line
        factory = protocol.ClientFactory()
        factory.protocol = ClientProtocol
        factory.originator = self
        reactor.connectTCP('localhost', 1234, factory)

    def forwardLine(self, recipient):
        recipient.sendLine(self._received)

class ClientProtocol(basic.LineReceiver):
    def connectionMade(self):
        self.factory.originator.forwardLine(self)
        self.transport.loseConnection()

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

    log.startLogging(sys.stdout)
    factory = protocol.ServerFactory()
    factory.protocol = ServerProtocol
    reactor.listenTCP(4321, factory)
    reactor.run()

if __name__ == '__main__':
    main()

Notice how:

  • I got rid of the __init__ method on ClientProtocol. ClientFactory calls its protocol with no arguments. An __init__ that requires an argument will result in a TypeError being raised. Additionally, ClientFactory already sets itself as the factory attribute of protocols it creates.
  • I gave ClientProtocol a reference to the ServerProtocol instance by setting the ServerProtocol instance as the originator attribute on the client factory. Since the ClientProtocol instance has a reference to the ClientFactory instance, that means it has a reference to the ServerProtocol instance.
  • I added the forwardLine method which ClientProtocol can use to direct ServerProtocol to do whatever your application logic is, once the ClientProtocol connection is established. Notice that because of the previous point, ClientProtocol has no problem calling this method.


来源:https://stackoverflow.com/questions/10807656/twisted-server-client-data-sharing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!