Я пытаюсь написать очень простой HTTP-сервер, который отправляет потоковое видео на сервер. Когда клиент подключается, программа get_video (вымышленная) запускается в другом процессе, и его стандартный вывод направляется к нам (в предположении, что get_video отправляет / передает потоковое видео на стандартный вывод). Я использую 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()
Это едва работает. Если я отправляю HTTP-запрос, используя wget <a href="http://localhost:8080/blah.mp4" rel="nofollow">http://localhost:8080/blah.mp4</a>
, все происходит как положено - видео передается в сокет клиента и добавляется в новый файл, blah.mp4.
Однако, если я создаю фиктивную HTML-страницу с <a href="http://localhost:8080/blah/mp4">download</a>
и затем пытаюсь «сохранить цель / ссылку как ...» по этой ссылке, программа get_video вызывается дважды. Второй раз, когда видео действительно отправляется на сокет клиента. Должна быть какая-то буферизация.
Обратите внимание на блок try/except
в send_video()
. Раньше я получал сообщение об ошибке «сломанный канал» (с использованием фиктивного метода HTML-страницы), указывающее на то, что сокет клиента не предназначен для записи. Я положил try/except
туда, чтобы попытаться игнорировать его.
Я довольно смущен. HTTP-запросы выглядят одинаково, я не уверен, что мой браузер (Firefox) делает по-другому, чтобы вызвать это.
Есть идеи?
Edit:
Заголовок от 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 запросах GET для метода фиктивной ссылки html. Я не вижу здесь ничего очевидного ...