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ブロードキャストを使わないことにしました。