使用另一个套接字/TCP/RPC服务扩展现有Twisted服务以获取服务信息

使用另一个套接字/TCP/RPC服务扩展现有Twisted服务以获取服务信息,twisted,twisted.web,twisted.internet,Twisted,Twisted.web,Twisted.internet,我正在基于实现一个基于Twisted的心跳客户端/服务器组合。这是我的第一个扭曲的项目 基本上,它由一个UDP侦听器(Receiver)组成,该侦听器在接收包时调用侦听器方法(DetectorService.update)。DetectorService始终保存当前活动/非活动客户端的列表(我对该示例进行了大量扩展,但核心仍然相同),从而可以对在指定超时期间似乎断开连接的客户端做出反应 这是从现场获取的来源: UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_

我正在基于实现一个基于Twisted的心跳客户端/服务器组合。这是我的第一个扭曲的项目

基本上,它由一个UDP侦听器(
Receiver
)组成,该侦听器在接收包时调用侦听器方法(
DetectorService.update
)。DetectorService始终保存当前活动/非活动客户端的列表(我对该示例进行了大量扩展,但核心仍然相同),从而可以对在指定超时期间似乎断开连接的客户端做出反应

这是从现场获取的来源:

UDP_PORT = 43278; CHECK_PERIOD = 20; CHECK_TIMEOUT = 15

import time
from twisted.application import internet, service
from twisted.internet import protocol
from twisted.python import log

class Receiver(protocol.DatagramProtocol):
    """Receive UDP packets and log them in the clients dictionary"""

    def datagramReceived(self, data, (ip, port)):
        if data == 'PyHB':
            self.callback(ip)

class DetectorService(internet.TimerService):
    """Detect clients not sending heartbeats for too long"""

    def __init__(self):
        internet.TimerService.__init__(self, CHECK_PERIOD, self.detect)
        self.beats = {}

    def update(self, ip):
        self.beats[ip] = time.time()

    def detect(self):
        """Log a list of clients with heartbeat older than CHECK_TIMEOUT"""
        limit = time.time() - CHECK_TIMEOUT
        silent = [ip for (ip, ipTime) in self.beats.items() if ipTime < limit]
        log.msg('Silent clients: %s' % silent)

application = service.Application('Heartbeat')
# define and link the silent clients' detector service
detectorSvc = DetectorService()
detectorSvc.setServiceParent(application)
# create an instance of the Receiver protocol, and give it the callback
receiver = Receiver()
receiver.callback = detectorSvc.update
# define and link the UDP server service, passing the receiver in
udpServer = internet.UDPServer(UDP_PORT, receiver)
udpServer.setServiceParent(application)
# each service is started automatically by Twisted at launch time
log.msg('Asynchronous heartbeat server listening on port %d\n'
    'press Ctrl-C to stop\n' % UDP_PORT)
因此,我需要向我的DetectorService添加一些额外的服务器(Socket、Tcp、RPC-这无关紧要。主要的一点是,我能够使用上述行为构建一个客户端脚本),它允许从外部连接到DetectorService。它应该只是对请求做出响应

此服务器需要访问正在运行的detectorservice实例的内部变量,因此我猜我必须使用某种附加服务扩展detectorservice

在尝试将detectorservice与其他几项服务结合几个小时之后,我仍然不知道实现这种行为的最佳方式是什么。所以我希望有人能给我一些基本的提示,告诉我如何开始解决这个问题。
提前感谢

我认为您已经了解了解决方案的总体思路,因为您已经将其应用于
接收器
检测器服务
之间的交互。这样做的目的是让您的对象具有对其他对象的引用,从而使它们能够执行需要执行的操作

这样,考虑一个Web服务,该请求响应基于“代码> Beats 数据:

from twisted.web.resource import Resource

class BeatsResource(Resource):
    # It has no children, let it respond to the / URL for brevity.
    isLeaf = True

    def __init__(self, detector):
        Resource.__init__(self)
        # This is the idea - BeatsResource has a reference to the detector,
        # which has the data needed to compute responses.
        self._detector = detector

    def render_GET(self, request):
        limit = time.time() - CHECK_TIMEOUT
        # Here, use that data.
        beats = self._detector.beats
        silent = [ip for (ip, ipTime) in beats.items() if ipTime < limit]
        request.setHeader('content-type', 'text/plain')
        return "%d silent clients" % (len(silent),)

# Integrate this into the existing application
application = service.Application('Heartbeat')
detectorSvc = DetectorService()
detectorSvc.setServiceParent(application)
.
.
.
from twisted.web.server import Site
from twisted.application.internet import TCPServer

# The other half of the idea - make sure to give the resource that reference 
# it needs.
root = BeatsResource(detectorSvc)
TCPServer(8080, Site(root)).setServiceParent(application)
从twisted.web.resource导入资源
类BeatsResource(资源):
#它没有子级,为了简洁起见,让它响应/URL。
isLeaf=True
def u u初始(自我,检测器):
资源.\uuuu初始化(自)
#这是想法-BeatsResource有一个探测器的参考,
#其中包含计算响应所需的数据。
自身检测器=检测器
def render_GET(自我,请求):
limit=time.time()-检查\u超时
#在这里,使用这些数据。
beats=self.\u detector.beats
静默=[ip for(ip,ipTime)在beats.items()中,如果ipTime<限制]
request.setHeader('content-type','text/plain')
返回“%d个静默客户端”%(len(静默),)
#将其集成到现有应用程序中
应用程序=服务。应用程序('Heartbeat')
detectorSvc=DetectorService()
detectorSvc.setServiceParent(应用程序)
.
.
.
从twisted.web.server导入站点
从twisted.application.internet导入TCPServer
#想法的另一半——确保为资源提供参考
#它需要。
根=BeatsResource(检测器SVC)
TCPServer(8080,站点(根)).setServiceParent(应用程序)

谢谢,我解决了我的问题。但是
TCPServer(8080,Site(root)).setServiceParent(application)
不起作用(Twisted中没有这样的类,Python中的TCPServer没有
setServiceParent
。我现在在我的代码中使用
reactor.listenTCP(8080,Site(root))
。@ifischer:有
t.a.I.TCPServer
类(它是动态生成的)。
from twisted.web.resource import Resource

class BeatsResource(Resource):
    # It has no children, let it respond to the / URL for brevity.
    isLeaf = True

    def __init__(self, detector):
        Resource.__init__(self)
        # This is the idea - BeatsResource has a reference to the detector,
        # which has the data needed to compute responses.
        self._detector = detector

    def render_GET(self, request):
        limit = time.time() - CHECK_TIMEOUT
        # Here, use that data.
        beats = self._detector.beats
        silent = [ip for (ip, ipTime) in beats.items() if ipTime < limit]
        request.setHeader('content-type', 'text/plain')
        return "%d silent clients" % (len(silent),)

# Integrate this into the existing application
application = service.Application('Heartbeat')
detectorSvc = DetectorService()
detectorSvc.setServiceParent(application)
.
.
.
from twisted.web.server import Site
from twisted.application.internet import TCPServer

# The other half of the idea - make sure to give the resource that reference 
# it needs.
root = BeatsResource(detectorSvc)
TCPServer(8080, Site(root)).setServiceParent(application)