今さらPython3 (76) - ネットワーク
引き続き11章。
- 作者: Bill Lubanovic,斎藤康毅,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/12/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
ネットワークの基本的なところを追いかけるのは、ここの主旨と違うのでPythonで手を動かせるところをカバーしていく。
UDP
まずは、udp_server.pyから。socket.socket()でソケットを作る、つまり口を開けるてな感じで、bind()のところでバインドすると言われてもそのままなので、ソケットに届いたデータを聞いてやるという意味と理解。recvfromでスタンバイOKってとこか。実際にデータを受け取ると、「呼んだ?」と送り返したらサーバーはクローズ。
udp_client.pyもだいたい同じだけど、ソケットを作って、サーバーに挨拶したら、こっちもお返事待ちの状態に入り、返事を受け取ったら終了しますってな具合だね。
サーバー側。
$ python3 udp_server.py Starting the server at 2015-12-28 11:38:53.558049 Waiting for a client to call. At 2015-12-28 11:39:41.591555 ('127.0.0.1', 49889) said b'Hey!' $
49889はクライアントのポート番号で、挨拶されたよという内容が出力されている。
クライアント側。
$ python3 udp_client.py Starting the client at 2015-12-28 11:39:41.588752 At 2015-12-28 11:39:41.591683 ('127.0.0.1', 6789) said b'Are you talking to me?' $
サーバーは自分で6789というポート番号を指定していたので、この番号でもってお返事したということ。
TCP/IP
UDPは高速だけど到達を保証しないという問題があるので、接続を確立してやりとりするTCP/IPを使いましょうということだね。
変わったところは、socketの引数の1つがSOCK_STREAMになっているのは、TCP/IPになったからだよね。
例によって、server側から起動して、
$ python3 tcp_server.py Starting the server at 2015-12-28 12:15:25.317374 Waiting for a client to call. At 2015-12-28 12:15:36.944858 <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6789), raddr=('127.0.0.1', 53646)> said b'Hey!'
client側を後から起動する。
$ python3 tcp_client.py Starting the client at 2015-12-28 12:15:36.941942 At 2015-12-28 12:15:36.944994 someone replied b'Are you talking to me?' $
実際に、このレベルのプログラミングが必要になるかどうかは微妙だけど、その時は、この文書を読むようにするつもり。
Socket Programming HOWTO — Python 3.5.1 documentation
ZeroMQ再び
前回触ったZeroMQはパブサブ(この略語はあまり好きじゃない)だけでなく、強化版ソケットとしても使えるということで再登場なんですね。ここには、Pythonのサンプルもいっぱい載っているそうなので、必要になったときのためにリンクを張っておく。
インストール済なので、さっそく試してみる。
Gistの関係で、クライアント側が上に出ているけど、サーバー側のソース(zqm_server.py)から見る。socketを作るときの引数にzmq.REPという同期応答が指定されている事以外は、これまで見てきたものと大差なく見える。一方のクライアント側(zmq_client.py)を見ると、ソケットの引数がzmq.REQ(同期要求)になっているところが目立つかな。メッセージを送って、戻りを受け取ってと言うあたりは、これまでも一緒。
サーバー、クライアントの順に起動するとこうなる。
$ python3 zmq_server.py & [1] 13729 python3 zmq_client.py That voice in my head says: message #1 Sent message #1, received Stop saying: message #1 That voice in my head says: message #2 Sent message #2, received Stop saying: message #2 That voice in my head says: message #3 Sent message #3, received Stop saying: message #3 That voice in my head says: message #4 Sent message #4, received Stop saying: message #4 That voice in my head says: message #5 Sent message #5, received Stop saying: message #5
&を使ってバックグラウンド処理にしているので、同じウィンドウからクライアントも起動できる。
$ python3 zmq_server.py Traceback (most recent call last): File "zmq_server.py", line 7, in <module> server.bind("tcp://%s:%s" % (host, port)) File "zmq/backend/cython/socket.pyx", line 487, in zmq.backend.cython.socket.Socket.bind (zmq/backend/cython/socket.c:5156) File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/socket.c:7535) zmq.error.ZMQError: Address already in use
いちおう、別ウィンドウでサーバーをもう1つ起動したときの怒られ方も確認。
あとは、本を読んでいて気がついたところを拾い読み。
このやりとりでは、文字列だけを使っていたので、encode/decodeで対応すれば良かったけど、他のデータ型を含む場合は、MessagePackなるものがあるらしい。
MessagePack: It's like JSON. but fast and small.
ZeroMQにブローカーを持たせるイメージ図だけど、あれはサービスA, B, C側にあるのはREQではなくてREPのような気がする。
scapyは、python3で一応使えるようになったみたい。みたいというのは、インストールだけしてまだ動かしてないから。
サイトには、一応こう説明してある。
This is a fork of scapy (packet dissection and manipulation tool) with added functionality, some bug fixes, and python3 compatibility.
$ pip3 install scapy-python3 Collecting scapy-python3 Downloading scapy-python3-0.18.tar.gz (2.1MB) 100% |████████████████████████████████| 2.1MB 261kB/s Building wheels for collected packages: scapy-python3 Running setup.py bdist_wheel for scapy-python3 Stored in directory: /Users/ken/Library/Caches/pip/wheels/a4/a1/ec/6ca7f94c3f4618af253473dfb86e588e1904f8898d2e805b98 Successfully built scapy-python3 Installing collected packages: scapy-python3 Successfully installed scapy-python3-0.18
とりあえずインストールが煩わしいということもなさそう。
(つづく)