Twisted - 将数据从服务器发送到客户端

4
我刚接触Twisted,读了很多类似于我遇到的问题的帖子。然而,我无法引申先前的答案来解决我的简单问题。我确实参考了Twisted的FAQ部分,但仍然不理解。
我的问题是,我有一个服务器在一个端口监听,并且当我收到“START”命令时,我想与几个客户端通信。例如,我使用一个单一的客户端,提供给我一个幸运饼干。但是,我无法从服务器代码中与客户端交流。请告诉我我哪里出错了?以下是代码:
from twisted.internet import reactor, protocol
from twisted.internet.protocol import Protocol, Factory

class FakeTelnet(Protocol):
    def connectionMade(self):
        print 'local connection made'
        self.otherFact = protocol.ClientFactory()
        self.otherFact.protocol = EchoClient
        self.factory.clients.append(self.otherFact.protocol)
        reactor.connectTCP('psrfb6',10999, self.otherFact)

    def dataReceived(self, data):

        if 'START' in data:
            # send a command to cookie server.
            for client in self.factory.clients:
                client.transport.write('START\r\n')

    def connectionLost(self):
        print 'connection lost'

class EchoClient(Protocol):
    """Once connected, send a message, then print the result."""

    def connectionMade(self):
        print "Connection to cookie server"

    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        print "Fortune Server said:", data

    def connectionLost(self):
        print "connection lost"

    def send_stuff(data):
        self.transport.write(data);

class MyFactory(Factory):
    protocol = FakeTelnet
    def __init__(self, EchoClient):
        self.clients = []
        self.otherCli = EchoClient

reactor.listenTCP(5823, MyFactory(EchoClient))
reactor.run()

简短更新:我查看了这个FAQ:http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#HowdoImakeinputononeconnectionresultinoutputonanother - 但仍然无法理解。我想要的是在FakeTelnet中建立的客户端连接可在dataReceived中使用。任何帮助将不胜感激。谢谢。 - RK1974
1个回答

5
class FakeTelnet(Protocol):
    def connectionMade(self):
        print 'local connection made'
        self.otherFact = protocol.ClientFactory()
        self.otherFact.protocol = EchoClient

在这里,你将self.otherFact.protocol设置为EchoClient类。

        self.factory.clients.append(self.otherFact.protocol)

在这里,您将EchoClient添加到self.factory.clients列表中。这只会导致self.factory.clients重复地充满EchoClient的列表。

def dataReceived(self, data):
    if 'START' in data:
        # send a command to cookie server.
        for client in self.factory.clients:
            client.transport.write('START\r\n')

在这里,你试图写入EchoClient.transport,通常情况下它将是None,因为只有协议类的实例才会连接到传输,而不是类本身。

尝试将已连接的实例添加到self.factory.clients中。我想你已经成功创建了这样的实例,因为你还在FakeTelnet.connectionMade中有这行代码:

    reactor.connectTCP('psrfb6',10999, self.otherFact)

然而,您没有执行任何操作将连接协议添加到self.factory.clients列表中。也许您可以像这样重新定义self.otherFact:

class OtherFactory(ClientFactory):
    protocol = EchoClient

    def __init__(self, originalFactory):
        self.originalFactory = originalFactory

    def buildProtocol(self, addr):
        proto = ClientFactory.buildProtocol(self, addr)
        self.originalFactory.clients.append(proto)
        return proto

在某些情况下,您还需要从clients列表中删除内容。也许是在协议的connectionLost回调函数中:

class EchoClient(Protocol):
    ...
    def connectionLost(self, reason):
        self.factory.originalFactory.clients.remove(self)

最后,如果你处理的是按行分隔的数据,你可能希望使用twisted.protocols.basic.LineOnlyReceiver作为FakeTelnet的基类,并将你的逻辑放在它的lineReceived回调中。 dataReceived回调不能保证数据边界,因此你可能永远不会看到一个包含"START"的单个字符串。例如,你可能会收到两个调用dataReceived的情况,一个是"ST",另一个是"ART"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接