我需要建议我应该使用选择还是线程?

Mic*_*l B 1 python multithreading http-live-streaming

我正在构建一个实时广播流媒体,我想知道我应该如何处理多个连接。现在,根据我的经验,选择将阻止音频流式传输。它只播放 3 秒然后停止播放。我将举例说明我的意思。

import socket, select

headers = """
HTTP/1.0 200 OK\n
Content-Type: audio/mpeg\n
Connection: keep-alive\n
\n\n
"""
file="/path/to/file.mp3"
bufsize=4096 # actually have no idea what this should be but python-shout uses this amount
sock = socket.socket()
cons = list()
buf = 0
nbuf = 0

def runMe():
    cons.append(sock)
    file = open(file)
    nbuf = file.read(bufsize) # current buffer
    while True:
        buf = nbuf
        nbuf = file.read(bufsize)
        if len(buf) == 0:
           break
        rl, wl, xl = select.select(cons, [], [], 0.2)
        for s in rl:
            if s == sock:
                  con, addr = s.accept()
                  con.setblocking(0)
                  cons.append(con)
                  con.send(header)
             else:
                  data = s.recv(1024)
                  if not data:
                     s.close()
                     cons.remove(s)
                  else:
                     s.send(buf)
Run Code Online (Sandbox Code Playgroud)

这是我如何使用选择的一个例子。但是,这首歌不会一直播放。但是如果我在选择循环之外发送它会播放但它会在第二次连接时死亡。我应该使用线程吗?

Jer*_*ner 5

这是我如何使用选择的一个例子。但是,这首歌不会一直播放。但是如果我在选择循环之外发送它会播放但它会在第二次连接时死亡。我应该使用线程吗?

您可以采用任何一种方式,但如果您的选择实现不能正常工作,那是因为您的代码不正确,而不是因为基于选择的实现无法完成这项工作——我不认为多线程解决方案比基于选择的解决方案更容易正确。

无论您选择哪种实现,您都必须考虑的一个问题是时间/吞吐量。您是否希望您的程序以与要播放的速度大致相同的速率发送音频数据,或者您是否希望以客户端愿意读取的速度发送音频数据,并将其留给客户端客户端以适当的速度读取数据?请记住,每个 TCP 流的发送速率会有所不同,这取决于客户端选择 recv() 信息的速度,以及您的服务器和客户端之间的网络路径的执行情况。

之后要处理的下一个问题是客户端速度慢的问题——当一个 TCP 连接非常慢时,例如由于网络拥塞,您希望您的程序做什么?现在你的代码只是盲目地在所有套接字上调用 send() 而不检查返回值,这(假设套接字是非阻塞的)意味着如果给定套接字的输出缓冲区已满,那么一些(可能很多)字节的该文件只会被删除 - 也许这符合您的目的,我不知道。客户端是否能够使用缺少任意部分的 mp3 数据流?我想,运行该客户端的人充其量只会听到故障。

抛开实现问题不谈,如果是我,我更喜欢单线程/select() 方法,因为它更容易测试和验证。两种方法都需要做一些事情才能正确,但是对于单个线程,您的程序的行为更具确定性 - 要么正常工作,要么不正常,并且运行给定的测试通常每次都会给出相同的结果(假设网络条件一致)。在多线程程序 OTOH 中,线程的调度是非确定性的,这使得很容易最终得到一个程序,该程序在 99.99% 的时间内正常工作,然后出现严重故障,但仅在蓝月亮中出现一次——一种很难调试的情况,因为您最终要花费数小时或数天来重现故障,更不用说诊断和修复它了。