PythonでUDPブロードキャスト
UDP Broadcast Server : UDP : Network : Python examples (example source code) Organized by topic を見たところ、簡単に実装できそうだったので、実際に動かして勉強することにしました。 結果、サーバが25行、クライアントが27行になりました。
素直に書いてしまうとサーバから何も送られてこない時にクライアントが待機状態に入ってしまって ハングアップしたように見えてしまいます。 UNIXではノンブロッキングモードというそうならないモードがあるようですが、 Windowsでは使えないので、selectモジュールを使ってブロックされないようにしました。
あとクライアント側で、データが来たかどうかにかかわらず同じ長さsleepしていると、 サーバがデータを送る頻度が高いときにどんどん取り残されていくので、 データが来ていたときにはsleepしないですぐ「次のデータは来ているかな?」とチェックするようにしました。
見よう見まねのコードですが、作っていて自分がだいぶ勉強になったのでシェアしたいと思います。 「そこは違う!」などのつっこみは大歓迎します。
サーバのコードがこちら。
import socket, traceback from time import sleep host = '' # Bind to all interfaces port = 51423 address = "10.89.107." s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.bind((host, port)) count = 0 while True: try: s.sendto(str(count), (address + "255", port)) print "sent", count sleep(0.8) count += 1 except (KeyboardInterrupt, SystemExit): break except: traceback.print_exc() break
クライアントのコードがこちら。
import socket, traceback from select import select from time import sleep host = '' # Bind to all interfaces port = 51423 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((host, port)) while True: try: ins, outs, errs = select([s], [], [], 0) if ins: for i in ins: message, address = i.recvfrom(8192) print "message:", message, "from", address else: print "none..." sleep(1) except (KeyboardInterrupt, SystemExit): break except: traceback.print_exc() break
このサーバスクリプトを1台のマシンで走らせ、 クライアントを複数のマシンで走らせてみると、 きちんと一つのプログラムが送り出した情報を複数のプログラムが受け取っていることがわかります。 めでたしめでたし。
追記。 このあとJavaでもブロードキャストやマルチキャストのコードを書いたのですが、ブロードキャストで毎秒40メガバイトのパケットをまき散らしたせいでラボのネットワークが大変なことになってしまいました。いろいろ考えた結果、今回作ろうとしているものにはUDPブロードキャストを使わないことにしました。