読者です 読者をやめる 読者になる 読者になる

zmq で REQ/REP を Erlang/Python でつないでみる

ErlangPython でメッセージのやりとりをしてみます。まずは Erlang が REQ で Python が REP です。
相変わらず同期ですが、テストはシンプルな方が良いので同期から。

サンプルコード

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

ここの 0d15313ab5c31bfb18e5d744286fa9fe250166fc です。

Python

REQ/REP で使ったコードそのままです。 print msg だけ追加しました。

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()
  print msg
  sock.send(msg)

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

loop.start()

Erlang

お作法に沿ってプロジェクトを作ってからやってみています。ただし ZMQ にあるサンプルは全部 escript になっているので、気軽に使えるようです。

rebar.config に erlzmq を設定します。erlzmq2 とかいてあるわりに app ファイルが erlzmq なので気をつけましょう。

{erl_opts, [warnings_as_errors,
            warn_export_all,
            warn_unused_import,
            warn_untyped_record]}.
{xref_checks, [fail_on_warning, undefined_function_calls]}.
{clean_files, [".test/*.beam", ".eunit/*", "ebin/*.beam"]}.
{cover_enabled, true}.
{validate_app_modules, true}.

{deps,
  [
   {erlzmq,
    ".*", {git, "git://github.com/zeromq/erlzmq2.git", {branch, "master"}}}
  ]
}.

まずは何も考えずに書いてみます。

-module(snowflake).

-export([main/0]).

main() ->
  {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"),
  erlzmq:send(Client, <<"Hello">>),
  {ok, Reply} = erlzmq:recv(Client),
  io:format("Reply: ~p", [Reply]),
  ok = erlzmq:close(Client),
  ok = erlzmq:term(Context),
  ok.

動かしてみる

Python

python rep.py

Erlang

$ ./rebar compile
$ erl -pa ebin deps/*/ebin

> application:start(erlzmq).
> snowflake:main()
Reply: <<"Hello">>ok

Erlang 側で Python が ECHO として返した、"Hello" が表示されました。
Python 側にも Hello が表示されていれば問題ありません。

シリアライズ/デシリアライズを試してみます。