0

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?

4

1 に答える 1

3

問題は単純なタイプミスです。

LineReceiverlineReceived各行でそのメソッドを呼び出します。あなたはそれをオーバーライドすることになっています。しかし、そうではなく、lineRecieved代わりに定義します。したがって、デフォルトの実装が得られます。これは を発生させNotImplementedます。


それを修正しても、コードはまだ少し奇妙です。通信をトレースします。

クライアントが接続すると、サーバーの が呼び出され、次のことが行われますUser.connectionMade

self.sendLine('username:')

したがって、クライアントはそれを取得して次のことをMain.dataReceived行います。

self.transport.write(data)

そのため、プロンプトを応答として送り返しています。

サーバーはそれを受け取りlineReceived(名前を修正したら)、次のようにします。

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

したがって、ユーザー名を に設定します'username:'

于 2013-07-12T23:15:42.107 に答える