繁体   English   中英

python发送http响应

[英]python sending http response

我正在尝试编写一个非常简单的HTTP服务器,该服务器发送正在服务器端流式传输的视频。 当客户端连接时,get_video程序(虚构的)将在另一个进程中启动,并且其stdout将通过管道传递给我们(假设get_video将视频发送/流式传输到stdout)。 我为此使用subprocess.Popen()

import subprocess, socket

def send_video(sock, programme_id):
    p = subprocess.Popen(["get_video","--pid",programme_id], stdout=subprocess.PIPE)
    sock.send("HTTP/1.1 200 OK\nContent-type: application/octet-stream\n\n")
    while True:
        chunk = p.stdout.read(1024)
        if chunk:
            try:
                sock.send(chunk)
            except Exception:
                pass
        else:
            break

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('',8080))
    s.listen(5)

    while True:
        client, address = s.accept()
        data = client.recv(1024)
        send_video(client, "123456")
        client.close()

if __name__ == "__main__":
    main()

这几乎行不通。 如果我使用wget http://localhost:8080/blah.mp4发出HTTP请求,则整个过程将按预期进行-视频将流式传输到客户端的套接字并附加到新文件blah.mp4。

但是,如果我使用<a href="http://localhost:8080/blah/mp4">download</a>创建了一个虚拟HTML页面,然后在该链接上尝试“将目标/链接另存为...”, get_video程序被调用两次。 第二次是将视频实际发送到客户端的套接字时。 必须进行某种缓冲。

注意send_video()try/except块。 之前(使用虚拟HTML页面方法),我遇到了“管道破裂”错误,指示该客户端的套接字没有被写入。 我把try/except放在那儿尝试忽略它。

我很困惑。 HTTP请求看起来相同,我不确定我的浏览器(Firefox)所做的不同以导致此问题。

有任何想法吗?

编辑:

wget的标头:

GET /blah.mp4 HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */*
Host: 192.168.1.2:8080
Connection: Keep-Alive

html虚拟页面的标题:

GET /blah.mp4 HTTP/1.1
Host: 192.168.1.2:8080
User-Agent: Mozilla/5.0 (blah) Gecko/blah Firefox/3.6.16
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

python服务器只报告了每个,但Wireshark报告了2个针对虚拟html链接方法的GET请求。 我在这里看不到任何明显的东西...

我突然意识到,因为在链接上单击“目标另存为...”后,浏览器发送GET,然后发送FIN,ACK,这将是导致管道断开错误的原因。 当您选择要保存文件的位置并在浏览器中单击“确定”按钮时,将发出另一个GET。 发生的事情是, while True我检测到管道破裂时,我仍然停留在while True循环中。 因此,我一直在继续读取Popen对象,并且每次都没有将其发送给客户端。 完成此操作后,下一个GET就可以继续,然后传输成功。 ew

简而言之,工作代码:

import subprocess, socket

def send_video(sock, programme_id):
    p = subprocess.Popen(["get_video","--pid",programme_id], stdout=subprocess.PIPE)
    sock.send("HTTP/1.1 200 OK\nContent-type: application/octet-stream\n\n")
    while True:
        chunk = p.stdout.read(1024)
        if chunk:
            try:
                sock.send(chunk)
            except socket.error, e:
                sock.close()
                break
        else:
            break

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('',8080))
    s.listen(5)

    while True:
        client, address = s.accept()
        data = client.recv(1024)
        send_video(client, "123456")
        client.close()

if __name__ == "__main__":
    main()

谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM