PythonワンライナーでUSBミサイルランチャーを制御 [Main] PythonからUSBミサイルランチャを操作する短いサンプル

PythonワンライナーでUSBミサイルランチャーを制御[Python(18)]PythonからUSBミサイルランチャを操作する短いサンプル

[UDP(1)]

Pythonで日本語PDFをつくる短いサンプル[短いサンプル(3)]PythonからUSBミサイルランチャを操作する短いサンプル

PythonでUDPブロードキャスト

ネットワークに関しては素人なので勉強中の西尾です。 UDPについて調べていたらDatagramという単語が出てきたので、 何だろうと思って調べてみたのですが、 そもそもUDPはUser Datagram Protocolの略でした。(´・ω・`)

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