我正在构建一个实时无线电流媒体,我想知道应该如何处理多个连接。根据我的经验,现在select将阻止音频流式传输。它只播放3秒,然后停止播放。我将举例说明我的意思。
import socket, select
headers = """
HTTP/1.0 200 OKn
Content-Type: audio/mpegn
Connection: keep-aliven
nn
"""
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)
这是我如何使用select的一个例子。但是,这首歌不会一直播放下去。但如果我在选择循环之外发送,它会播放,但在第二次连接时会失效。我应该使用螺纹吗?
这是我如何使用select的一个例子。但是,这首歌不会播放一路走来。但如果我在选择循环之外发送,它会播放,但它会在第二次连接时死亡。我应该使用螺纹吗?
你可以用任何一种方式来做,但如果你的选择实现不能正常工作,那是因为你的代码不正确,而不是因为基于选择的实现不能胜任这项工作——我认为多线程解决方案不会比基于选择的解决方案更容易做对。
无论您选择哪种实现,您都必须考虑的一个问题是时间/吞吐量。您希望您的程序以与播放速率大致相同的速率发送音频数据,还是希望以客户端愿意读取的速度发送音频数据并让客户端以适当的速度读取数据?请记住,每个TCP流的发送速率都会有所不同,这取决于客户端选择接收()信息的速度,以及服务器和客户端之间的网络路径的性能。
之后要处理的下一个问题是客户端速度慢的问题——当其中一个TCP连接非常慢时,例如由于网络拥塞,你希望你的程序做什么?现在,您的代码只是在所有套接字上盲目地调用send(),而不检查返回值,这意味着(假设套接字是非阻塞的)如果给定套接字的输出缓冲区已满,那么文件的一些(可能很多)字节就会被丢弃——我不知道这是否符合您的目的。客户端是否能够使用缺少任意部分的mp3数据流?我想,运行该客户端的人最多也会听到故障。
撇开实现问题不谈,如果是我,我更喜欢单线程/select()方法,因为它更容易测试和验证。无论哪种方法都需要做一些工作才能正确,但对于单个线程,程序的行为都更具确定性——要么工作正常,要么不工作,运行给定的测试通常每次都会给出相同的结果(假设网络条件一致)。在多线程程序OTOH中,线程的调度是不确定的,这使得程序很容易在99.99%的时间内正常工作,然后出现严重故障,但只有一次是千载难逢的——这种情况可能很难调试,因为你最终花了数小时或数天的时间来重现故障,更不用说诊断和修复了。