Aquí hay una aplicación rápida de "prueba de concepto" utilizando el marco trenzado. Esto supone que el servicio UDP heredado está escuchando en localhost: 8000 y comenzará a enviar datos UDP en respuesta a un datagrama que contiene "Enviarme datos". Y que los datos son 3 enteros de 32 bits. Además es capaz de responder a un "HTTP GET /" en el puerto 2080.
Se podría empezar con este twistd -noy example.py
:
example.py
from twisted.internet import protocol, defer
from twisted.application import service
from twisted.python import log
from twisted.web import resource, server as webserver
import struct
class legacyProtocol(protocol.DatagramProtocol):
def startProtocol(self):
self.transport.connect(self.service.legacyHost,self.service.legacyPort)
self.sendMessage("Send me data")
def stopProtocol(self):
# Assume the transport is closed, do any tidying that you need to.
return
def datagramReceived(self,datagram,addr):
# Inspect the datagram payload, do sanity checking.
try:
val1, val2, val3 = struct.unpack("!iii",datagram)
except struct.error, err:
# Problem unpacking data log and ignore
log.err()
return
self.service.update_data(val1,val2,val3)
def sendMessage(self,message):
self.transport.write(message)
class legacyValues(resource.Resource):
def __init__(self,service):
resource.Resource.__init__(self)
self.service=service
self.putChild("",self)
def render_GET(self,request):
data = "\n".join(["<li>%s</li>" % x for x in self.service.get_data()])
return """<html><head><title>Legacy Data</title>
<body><h1>Data</h1><ul>
%s
</ul></body></html>""" % (data,)
class protocolGatewayService(service.Service):
def __init__(self,legacyHost,legacyPort):
self.legacyHost = legacyHost #
self.legacyPort = legacyPort
self.udpListeningPort = None
self.httpListeningPort = None
self.lproto = None
self.reactor = None
self.data = [1,2,3]
def startService(self):
# called by application handling
if not self.reactor:
from twisted.internet import reactor
self.reactor = reactor
self.reactor.callWhenRunning(self.startStuff)
def stopService(self):
# called by application handling
defers = []
if self.udpListeningPort:
defers.append(defer.maybeDeferred(self.udpListeningPort.loseConnection))
if self.httpListeningPort:
defers.append(defer.maybeDeferred(self.httpListeningPort.stopListening))
return defer.DeferredList(defers)
def startStuff(self):
# UDP legacy stuff
proto = legacyProtocol()
proto.service = self
self.udpListeningPort = self.reactor.listenUDP(0,proto)
# Website
factory = webserver.Site(legacyValues(self))
self.httpListeningPort = self.reactor.listenTCP(2080,factory)
def update_data(self,*args):
self.data[:] = args
def get_data(self):
return self.data
application = service.Application('LegacyGateway')
services = service.IServiceCollection(application)
s = protocolGatewayService('127.0.0.1',8000)
s.setServiceParent(services)
Afterthought
Este no es un diseño de WSGI. La idea de esto sería utilizar para ejecutar este programa desmemoriado y tener su puerto http en una IP local y apache o similar a las solicitudes de proxy. Podría ser refactorizado para WSGI. Fue más rápido golpear de esta manera, más fácil de depurar.
No hay "continuo" en HTTP. Por definición. No puede haber ¿Que estas pidiendo? ¿Una versión milagrosa del protocolo HTTP que de alguna manera no sigue las reglas HTTP y en su lugar se comporta como UDP? –
Gracias por su preocupación. Sé que tal cosa no existe. Para aclarar: mi problema es tratar de leer instantáneas de datos UDP a través de HTTP. No estoy tratando de hacer HTTP "continuo" (la pregunta también fue editada) – jsalonen
Una buena estructura para usar sería tener algún tipo de modelo de las variables en una aplicación web implementada de alguna manera. La información UDP actualiza ese modelo (es decir, la aplicación web lo escucha) pero no dice nada de HTTP para actualizar. Cualquier recuperación de HTTP solo lee una instantánea del estado actual de esas variables (y recuerda deshabilitar el almacenamiento en caché de las páginas generadas). –