Mark Grey
Mark Grey

Reputation: 10257

Twisted client protocol - attaching an interface frontend

I am following the tutorial on writing a client/server pair in Twisted located here:

http://twistedmatrix.com/documents/current/core/howto/clients.html

I have everything working for the communication of my client and server, the system uses custom prefixes to denote how far it is into the 'conversation'. It sends a json string initially to set up the session, and then sends a file line by line. It's really just an exercise more than anything else.

Client.py:

class ClientProtocol(protocol.Protocol):

    def connectionMade(self):
        json_string = json.dumps({
            'uid':ObjectId(),
            'lat':43.78,
            'lon':-72.5831
        },cls=Encoder)
        self.transport.write('OPN|'+json_string)
        self.fileObject = open('test.csv')

    def sendFile(self):
        lineData = self.fileObject.readline()
        if lineData != '':
            self.transport.write('UPD|')
            self.transport.write(lineData)
        else:
            self.transport.write('EOF|done')

    def dataReceived(self,data):
        if data in ['ELLO','RECVD']:
            self.sendFile()


class ClientFactory(protocol.Factory):
    def buildProtocol(self,addr):
        return ClientProtocol()

if __name__ == '__main__':
    point = TCP4ClientEndpoint(reactor,'localhost',5000)
    d = point.connect(ClientFactory())
    reactor.run()

Server:

    class TransferProtocol(protocol.Protocol):

        ran = 0

        def connectionLost(self,reason):
            print reason

        def connectionMade(self):
            self.fileObject = open('output','w')

        def dataReceived(self,data):
            methods = {'OPN':'open','UPD':'upload','EOF':'endfile'}
            if data[0:3] in methods.keys():
                func = getattr(self,methods[data[0:3]])
                func(data[4:])

        def open(self,data):
            print 'OPEN %s' % data
            self.transport.write('ELLO')

        def endfile(self,data):
            print 'END %s' % data
            self.transport.loseConnection()

        def upload(self,data):
            self.ran+=1
            self.fileObject.write(data)
            self.transport.write('RECVD')

class myProtocolFactory(protocol.Factory):
    protocol = TransferProtocol

    def doStart(self):
        pass

    def startedConnecting(self, connectorInstance):
        print connectorInstance

    def buildProtocol(self, address):
        print address
        return self.protocol()

    def clientConnectionLost(self, connection, reason):
        print reason
        print connection

    def clientConnectionFailed(self, connection, reason):
        print connection
        print reason

    def doStop(self):
        pass

if __name__ == '__main__':
    reactor.listenTCP(5000, myProtocolFactory())
    reactor.run()

Currently, I run the server in one terminal and the client in another. As expected, both reactors start and communicate once, the client transmits it's identity json followed by the file contents and then terminates the connection. What I can't understand is how to 'hook up' this protocol to something like the cmd interface, to make it spawn these processes on command after one ends. Because the reactor in the client runs indefinitely, it performs the network conversation once and then just loops through continuously in the reactor.

Everything I've ever build with Twisted, client or server, just responded to network calls, so I am wondering what would be the correct approach to making this a "one-shot" client protocol that would activate on input commands from cmd. Would one even use the reactor for something like this? Or Twisted at all for that matter as opposed to just manually opening sockets that follow the protocol?

EDIT

I've found the Twisted stdio library fishing around on google and SO, but I'm having trouble hooking the terminal input protocol up to the network protocol.

I have the terminal protocol inherit for LineReceiver, and the prompts show correctly. I've assigned the network factory to the terminal protocol's factory object, and then attempt to call methods of the network protocol from the prompt. The problem is, the connector object assigned to this property doesn't use any of the methods of the protocol it's supposed to create.

I've put it on GitHub for brevity's sake:

https://github.com/DeaconDesperado/swfty-share/blob/master/client.py

Upvotes: 0

Views: 756

Answers (1)

pyfunc
pyfunc

Reputation: 66709

No There is no need for external wiring for bringing both your server and client services up together.

Twisted provides the necessary means to ensure that it can start all your services and bring them down when you shut down a twisted application. It provides the facility to do this.

Read this excellent tutorial on twisted application:

  1. http://krondo.com/?p=2345

Read the following for more details:

  1. http://twistedmatrix.com/documents/current/core/howto/basics.html
  2. http://twistedmatrix.com/documents/current/core/howto/application.html
  3. http://twistedmatrix.com/documents/current/core/howto/plugin.html
  4. http://twistedmatrix.com/documents/current/core/howto/tap.html

On SO:

  1. Twisted application without twistd

Upvotes: 1

Related Questions