使用Twisted的twisted.web类,如何刷新传出缓冲区?

Han*_*son 9 python twisted multipart-mixed-replace

我使用Twisted创建了一个简单的http服务器,它发送Content-Type:multipart/x-mixed-replace标头.我正在使用它来测试我想要设置为接受长期流的http客户端.

出现的问题是我的客户端请求挂起,直到http.Request调用self.finish(),然后它立即接收所有多部分文档.

有没有办法手动将输出缓冲区刷新到客户端?我假设这就是为什么我没有收到单独的多部分文件.

#!/usr/bin/env python

import time

from twisted.web import http
from twisted.internet import protocol

class StreamHandler(http.Request):
    BOUNDARY = 'BOUNDARY'

    def writeBoundary(self):
        self.write("--%s\n" % (self.BOUNDARY))

    def writeStop(self):
        self.write("--%s--\n" % (self.BOUNDARY))

    def process(self):
        self.setHeader('Connection', 'Keep-Alive')
        self.setHeader('Content-Type', "multipart/x-mixed-replace;boundary=%s" % (self.BOUNDARY))

        self.writeBoundary()

        self.write("Content-Type: text/html\n")
        s = "<html>foo</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()
        time.sleep(2)

        self.write("Content-Type: text/html\n")
        s = "<html>bar</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()
        time.sleep(2)

        self.write("Content-Type: text/html\n")
        s = "<html>baz</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)

        self.writeStop()

        self.finish()

class StreamProtocol(http.HTTPChannel):
    requestFactory = StreamHandler

class StreamFactory(http.HTTPFactory):
    protocol = StreamProtocol


if __name__ == '__main__':
    from twisted.internet import reactor
    reactor.listenTCP(8800, StreamFactory())
    reactor.run()
Run Code Online (Sandbox Code Playgroud)

nos*_*klo 10

使用time.sleep()可防止扭曲完成其工作.为了使它工作你不能使用time.sleep(),你必须将控制返回到扭曲.修改现有代码的最简单方法是使用twisted.internet.defer.inlineCallbacks,这是自切片面包以来的最佳选择:

#!/usr/bin/env python

import time

from twisted.web import http
from twisted.internet import protocol
from twisted.internet import reactor
from twisted.internet import defer

def wait(seconds, result=None):
    """Returns a deferred that will be fired later"""
    d = defer.Deferred()
    reactor.callLater(seconds, d.callback, result)
    return d

class StreamHandler(http.Request):
    BOUNDARY = 'BOUNDARY'

    def writeBoundary(self):
        self.write("--%s\n" % (self.BOUNDARY))

    def writeStop(self):
        self.write("--%s--\n" % (self.BOUNDARY))

    @defer.inlineCallbacks
    def process(self):
        self.setHeader('Connection', 'Keep-Alive')
        self.setHeader('Content-Type', "multipart/x-mixed-replace;boundary=%s" % (self.BOUNDARY))

        self.writeBoundary()

        self.write("Content-Type: text/html\n")
        s = "<html>foo</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()


        yield wait(2)

        self.write("Content-Type: text/html\n")
        s = "<html>bar</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)
        self.writeBoundary()

        yield wait(2)

        self.write("Content-Type: text/html\n")
        s = "<html>baz</html>\n"
        self.write("Content-Length: %s\n\n" % (len(s)))
        self.write(s)

        self.writeStop()

        self.finish()


class StreamProtocol(http.HTTPChannel):
    requestFactory = StreamHandler

class StreamFactory(http.HTTPFactory):
    protocol = StreamProtocol


if __name__ == '__main__':   
    reactor.listenTCP(8800, StreamFactory())
    reactor.run()
Run Code Online (Sandbox Code Playgroud)

这适用于Firefox,我想它正确回答了你的问题.