簡體   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