3

我使用 Twisted 创建了一个具有自定义协议的服务器,并且我有客户端连接到特定端口(例如端口 1234)上的服务器。我正在寻找基于某种网页的服务器控制界面。到目前为止,我的研究表明 Nevow 是流行的选择,但我只需要一些非常简单的东西。

例如,每次浏览器访问端口 8080 上的 hello world 页面时,我都会向连接在 1234 上的客户端发送一条消息。

我对如何将这两个连接在一起有点困惑。我假设我需要从 HelloResource.render_GET 调用 Server.message ?

from twisted.internet import protocol, reactor
from twisted.web.resource import Resource

    class Server(protocol.Protocol):
        def dataReceived(self, data):
            #do something on the server side

        def message(self)
            #send message to clients

    class HelloResource(Resource):
        isLeaf = True

        def render_GET(self,request):
            return "<html>Hello, world!</html>"

factory = protocol.Factory()
factory.protocol = Server
reactor.listenTCP(1234, factory)

reactor.listenTCP(8080, server.Site(HelloResource()))

reactor.run()
4

2 回答 2

5

这与 Twisted FAQ 中回答的问题非常相似。

本质上,您需要使您的工厂创建的协议实例可以访问构成您的 Web 服务器的资源。

一个简单的方法是让你的工厂保留一个协议实例列表(buildProtocol如果你还没有的话,请阅读),然后将工厂实例传递给你的HelloResource初始化器,然后让初始化器将工厂保存为HelloResource实例的属性.

这将HelloResource访问协议实例列表——通过它现在引用的工厂对象——然后它可以对其进行迭代,例如,在每个协议实例上调用方法。

于 2013-02-28T22:53:12.713 回答
1

如果你想以这种方式做事,你Server.message显然必须是 a @classmethod,并且它必须有权访问客户列表,并将消息发送给每个客户。

像这样的东西:

class Server(protocol.Protocol):
    clients = set()

    def dataReceived(self, data):
        #do something on the server side
        pass

    def connectionMade(self):
        Server.clients.add(self)

    def connectionLost(self):
        Server.clients.remove(self)

    @classmethod
    def message(cls):
        for client in cls.clients:
            client.transport.write('got GET request\n')

现在您可以Server.message()从您的render_GET方法中调用。

我不确定这是不是最好的设计——实际上,有各种比协议类更好的对象可以挂载客户端列表——但它应该可以工作。

于 2013-02-28T23:03:56.423 回答