zmq で Erlang/Python のデータのやりとりに JSON を使う

通信が確認出来たので、シリアライズしたデータを渡すテストです。
色々ありますが、まずは簡単な JSON データにしてみました。

ソースコード

https://github.com/voluntas/snowflake/tree/feature/zmq

git checkout 7c153e853e624b9aeefe6c0e83003b92c8ecbd32 してください。

Erlang

JSON のデコード/エンコードには jiffy という NIF で書かれた JSON ライブラリを使う事にしました。

コード自体はほとんど変わって無く、渡すデータを JSON にしてみているだけです。

-module(snowflake).

-export([main/0]).

main() ->
  application:start(erlzmq),
  application:start(jiffy),
  {ok, Context} = erlzmq:context(),
  {ok, Client} = erlzmq:socket(Context, [req]),
  ok = erlzmq:setsockopt(Client, identity, pid_to_list(self())),
  ok = erlzmq:connect(Client, "tcp://127.0.0.1:5555"),
  Request = jiffy:encode({[{foo, [<<"bing">>, 2.3, true]}]}),
  io:format("Request(encoded): ~w", [Request]),
  erlzmq:send(Client, Request),
  {ok, Reply} = erlzmq:recv(Client),
  Term = jiffy:decode(Reply),
  io:format("Reply(decoded): ~w", [Term]),
  ok = erlzmq:close(Client),
  ok = erlzmq:term(Context),
  ok.

Python

コードが変わったのは recv_json と send_json という関数を使うようにしました。
これらは pyzmq に最初から入っている関数です。

import zmq
from zmq.eventloop import ioloop

loop = ioloop.IOLoop.instance()

ctx = zmq.Context()
sock = ctx.socket(zmq.REP)
sock.bind('tcp://127.0.0.1:5555')

def rep_handler(sock, events):
  msg = sock.recv_json()
  print msg
  sock.send_json(msg)

loop.add_handler(sock, rep_handler, zmq.POLLIN)

loop.start()

確認

Python 側を起動します

$ python /rep.py
{'foo': ['bing', 2.3, True]}

Erlang 側を起動すると、ちゃんと Python 側からデータが送られてくることを確認出来ました。

$ erl -pa ebin deps/*/ebin
1> snowflake:main().
Request(encoded): <<123,34,102,111,111,34,58,91,34,98,105,110,103,34,44,50,46,50,57,57,57,57,57,57,57,57,57,57,57,57,57,57,56,50,50,52,44,116,114,117,101,93,125>>Reply(decoded): {[{<<102,111,111>>,[<<98,105,110,103>>,2.3,true]}]}ok

Python が PUB で Erlang が SUB(gen_server) をやってみようと思います。