DoctorSelar
DoctorSelar

Reputation: 484

Connect to Twisted TCP server

I have set up a TCP server using the twisted example (with some modifications).

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
from os import path

import yaml

class User(LineReceiver):
    def __init__(self,users):
        self.users = users
        self.name = None

    def connectionMade(self):
        print 'new connection'
        self.sendLine('username:')

    def connectionLost(self,reason):
        print 'connection lost'
        if not self.name == None:
            msg = '%s has disconnected' % (self.name)
            print msg
            self.toAll(msg,None)
            del self.users[self.name]

    def lineRecieved(self,line):
        print line
        if self.name == None:
            self.setName(line)
        else:
            self.toChat(line)

    def toAll(self,msg,to_self):
        for name, protocol in self.users.iteritems():
            if protocol == self and not to_self == None:
                self.sendLine(to_self)
            else:
                protocol.sendLine(msg)

    def setName(self,name):
        if self.users.has_key(name):
            self.sendLine('username in use')
            return
        elif ' ' in name:
            self.sendLine('no spaces!')
            return
        print 'new user %s' % (name)
        self.sendLine('logged in as %s' % (name))
        self.name = name
        self.users[name] = self

    def toChat(self,message):
        msg = '<%s> %s' % (self.name,message)
        print msg
        to_self = '<%s (you)> %s' % (self.name,message)
        self.toAll(msg,to_self)


class Main(Factory):
    def __init__(self,motd=None):
        self.users = {}
        self.motd = motd
        print 'loaded, waiting for connections...'

    def buildProtocol(self,addr):
        return User(self.users)

if not path.isfile('config.yml'):
    open('config.yml','w').write('port: 4444\nmotd: don\'t spam')

with open('config.yml','r') as f:
    dump = yaml.load(f.read())
    motd = dump['motd']
    port = dump['port']

reactor.listenTCP(port,Main(motd=motd))
reactor.run()

I was wondering how I would be able to connect to it? I've tried adapting their example Echo client and Echo server, but my server only gives a giant error when data is sent back to it.

(The echo server is here and the echo client is here)

The client I am using is

from twisted.internet import reactor
from twisted.internet.protocol import Protocol,ClientFactory

class Main(Protocol):
    def dataReceived(self,data):
        print data
        self.transport.write(data)

class MainFactory(ClientFactory):
    def buildProtocol(self,addr):
        print 'connected'
        return Main()

    def clientConnectionLost(self,connector,reason):
        print 'connection lost'

    def clientConnectionFailed(self,connector,reason):
        print 'connection failed'

reactor.connectTCP('localhost',4444,MainFactory())
reactor.run()

Here is a picture of the error

Image of error

What do I need to do to send data back to the server? What class do I need to inherit from?

Upvotes: 0

Views: 3876

Answers (1)

abarnert
abarnert

Reputation: 365657

The problem is a simple typo.

LineReceiver calls its lineReceived method on each line. You're supposed to override that. But you don't, you define lineRecieved instead. So, you get the default implementation, which raises NotImplemented.


If you fix that, your code is still more than a little odd. Trace through the communication.

The client connects, which calls the server's User.connectionMade, which does this:

self.sendLine('username:')

So the client gets that in Main.dataReceived and does this:

self.transport.write(data)

So, it's sending the prompt back as a response.

The server will receive that in lineReceived (once you fix the name) and do this:

if self.name == None:
    self.setName(line)

So, you're going to set the username to 'username:'.

Upvotes: 3

Related Questions