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