2016-04-15 12 views
1

私はライブラジオストリーマーを構築していますが、どうやって複数の接続を処理するべきか不思議でした。今私の経験から選択すると、オーディオがストリーミングされるのがブロックされます。 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を使用する方法の例です。しかし、その歌はずっと再生されません。しかし、私がselectループの外に送ると、それは再生されますが、それは2番目の接続で死ぬでしょう。スレッディングを使うべきですか?

+0

あなたは_output_アベイラビリティも制御したいですか? 'socket.send'もあなたのコードをブロックする可能性のある操作です – user3159253

+0

また、これは完全な実例かもしれません。 – user3159253

+0

スレッドと選択は2つの非常に異なるものです。ほとんどの場合、両方を使用する必要があります。あるいは、ねじれたようなフレームワークを使用しています(他にもうまくいきます)。 –

答えて

3

これはselectを使用する方法の例です。しかし、歌は のすべての方法で再生されません。しかし、私がselectループの外に送ると、それは再生されますが、 2番目の接続で死ぬでしょう。スレッディングを使うべきですか?

どちらの方法でも実行できますが、選択実装が正しく機能しない場合は、コードが正しくないためです。選択ベースの実装ではジョブを実行できないためではありません。マルチスレッドのソリューションは、選択ベースのソリューションよりも簡単に取得できるとは考えていません。

どの実装を選択しても、タイミング/スループットについて考える必要があります。あなたのプログラムは、それが再生されるのとほぼ同じ速度でオーディオデータを送信するようにしたいのですか、またはクライアントがそれを読みたいと思うほど速くオーディオデータを送りたいのですか?適切な速度でデータを読み取るクライアント?クライアントがどのくらい速く情報をrecv()するか、サーバーとクライアント間のネットワークパスがどれくらいうまくいくかによって、各TCPストリームの送信レートは異なります。

これに対処する次の問題は、低速クライアントの問題です.TCP接続の1つが非常に遅い場合、プログラムで何をしたいのですか?ネットワークの輻輳のために?今ではあなたのコードは返り値をチェックせずにすべてのソケットに対してsend()を呼びます(ソケットが非ブロックであることを考えると、指定されたソケットの出力バッファがいっぱいであれば、ファイルは単純に削除されます - おそらくあなたの目的のために大丈夫です、私は知らない。クライアントは、任意のセクションが欠落しているmp3データストリームを利用することができますか?私はそのクライアントを実行している人がうまくいけば何かを聞くだろうと思っています。

実装上の問題はさておき、テストと検証が簡単になるため、シングルスレッド/ select()アプローチが好きです。いずれのアプローチでも正しい結果が得られるはずですが、スレッドが1つの場合、プログラムの動作はより決定的です。正しく動作するかどうかは決まっていません。また、テストを実行すると、 (一貫したネットワーク条件を仮定して)。 OTOHのマルチスレッド・プログラムでは、スレッドのスケジューリングが非決定論的なので、99.99%の時間で正常に動作し、次に深刻な誤動作を起こすプログラムで終わるのは非常に簡単ですが、これは、デバッグが非常に困難な状況です。障害を再現するだけで数時間か数日を費やしてしまい、診断と修正はできません。

+0

"あなたのコードは返り値をチェックせずにすべてのソケットに対してsend()を呼びます。"あなたの答えが素晴らしいとは限りません。ただその部分を理解できませんでした。戻り値で、あなたはrecvを意味しますか?私がソケットを完全に理解していない限り、それは本当らしいです。私はクライアントが切断するかどうかをチェックする方法が必要だったので、recvのデータだけがそこにあります。しかし、サーバーが行う唯一のことは、接続されているすべてのブラウザーにmp3データを送信することです。それが誰にでも送信される理由です。私はまだPythonの専門家ではないので、私はewを聞かせて申し訳ありません。ちょうど良い理解を得ることを試みる。 –

+0

私は、あなたがs.send(buf)を呼び出すと、send()が返す値で何もしない(つまり、 'numBytesSent = s.send(buf)'をしないで、 numBytesSentの値に基づく適切なアクション)。ノンブロッキングソケットを使用しているので、send()コールは、送信を要求したバイトをすべて送信しなかった可能性が高いですが、実際に送信されたバイト数を知る方法はありません。戻り値 –

+0

私はsend()が何かを返すのを知らなかった、毎日新しいものを学ぶ。 –

関連する問題