2017-09-19 122 views
1

我想在Elixir和Python之間進行通信。我不想使用NIF和其他東西 - 我寧願使用zeroMQ進行鬆散耦合,因爲這將允許我以後使用Python以外的其他語言。我正在使用chumak庫,它是Erlang的zeromq的本地實現,並且看起來很好。過去,我已經成功地將它用於pub sub。ZeroMQ經銷商套接字不能在Elixir下工作(使用Erlang的chumak)

除了pub-sub,我發現req-rep和req-router套接字工作正常。然而經銷商路由器沒有。這非常重要,因爲只有經銷商和路由器才能在zeromq中爲您提供真正的異步。

下面是路由器端的Python代碼:

import zmq 
context = zmq.Context() 
rout = context.socket(zmq.ROUTER) 
rout.bind("tcp://192.168.1.192:8760") 

這裏是藥劑REQ代碼的正常工作......

iex(1)> {ok, sock1} = :chumak.socket(:req, 'reqid') 
{:ok, #PID<0.162.0>} 
iex(2)> {ok, _peer} = :chumak.connect(sock1, :tcp, '192.168.1.192', 8760) 
{:ok, #PID<0.164.0>} 
iex(3)> :chumak.send(sock1, 'hello from req socket') 
:ok 

....因爲我得到它的Python端:

In [5]: xx = rout.recv_multipart() 
In [6]: xx 
Out[6]: ['reqid', '', 'hello from req socket'] 

然而,這裏是我所得到的,如果我嘗試在藥劑側經銷商插座:

iex(4)> {ok, sock2} = :chumak.socket(:dealer, 'dealid')     
{:ok, #PID<0.170.0>} 
iex(5)> {ok, _peer} = :chumak.connect(sock2, :tcp, '192.168.1.192', 8760) 
{:ok, #PID<0.172.0>} 
iex(6)> :chumak.send(sock2, 'hello from dealer socket') 
{:error, :not_implemented_yet} 
iex(7)> :chumak.send_multipart(sock2, ['a', 'b', 'hello from dealer socket']) 

22:13:38.705 [error] GenServer #PID<0.172.0> terminating 
** (FunctionClauseError) no function clause matching in :chumak_protocol.encode_more_message/3 
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl:676: :chumak_protocol.encode_more_message('a', :null, %{}) 
    (stdlib) lists.erl:1354: :lists.mapfoldl/3 
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl:664: :chumak_protocol.encode_message_multipart/3 
    (chumak) /home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_peer.erl:159: :chumak_peer.handle_cast/2 
    (stdlib) gen_server.erl:616: :gen_server.try_dispatch/4 
    (stdlib) gen_server.erl:686: :gen_server.handle_msg/6 
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3 
Last message: {:"$gen_cast", {:send, ['a', 'b', 'hello from dealer socket'], {#PID<0.160.0>, #Reference<0.79795089.2401763329.172383>}}} 
State: {:state, :ready, '192.168.1.192', 8760, :client, [], :dealer, 'dealid', [], {3, 0}, #Port<0.4968>, {:decoder, :ready, 0, nil, nil, {:some, 3}, {:some, 0}, %{}, :null, false}, #PID<0.170.0>, {[], []}, [], false, false, false, :null, %{}} 

22:13:38.710 [info] [:unhandled_handle_info, {:module, :chumak_socket}, {:msg, {:EXIT, #PID<0.172.0>, {:function_clause, [{:chumak_protocol, :encode_more_message, ['a', :null, %{}], [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl', line: 676]}, {:lists, :mapfoldl, 3, [file: 'lists.erl', line: 1354]}, {:chumak_protocol, :encode_message_multipart, 3, [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_protocol.erl', line: 664]}, {:chumak_peer, :handle_cast, 2, [file: '/home/tbrowne/code/elixir/chutest/deps/chumak/src/chumak_peer.erl', line: 159]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 616]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 686]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}}] 

正如你可以看到我得到這個巨大的錯誤的:chumak.send_multipart,而:chumak.send甚至不工作。這裏發生了什麼?

經銷商插座工作正常的方式從Python方:

import zmq 
context = zmq.Context() 
deal = context.socket(zmq.DEALER) 
deal.setsockopt_string(zmq.IDENTITY, u"Thomas") 
deal.connect("tcp://192.168.1.192:8760") 
deal.send("hello from python deal") 

現在在路由器端:

In [5]: xx = rout.recv_multipart() 
In [6]: xx 
Out[6]: ['reqid', '', 'hello from req socket'] 
In [7]: dd = rout.recv_multipart() 
In [8]: dd 
Out[8]: ['Thomas', 'hello from python deal'] 

所以我不知道如果我有一個語法,或錯誤類型,在我的Elixir chumak經銷商插座中,或者它只是一個錯誤。我在amd64和armv7l架構上都試過這個,問題是一樣的。

所有elixir代碼都基於經銷商路由器的chumak example的Erlang版本。

我mix.exs DEPS看起來是這樣的:

[ 
     {:chumak, "~> 1.2"}, 
     {:msgpack, "~> 0.7.0"} 

] 

回答

2

我看到的唯一明顯的一點就是你的send_multipart的使用。它在源簽名:

-spec send_multipart(SocketPid::pid(), [Data::binary()]) -> ok. 

你這樣做:

:chumak.send_multipart(sock2, ['a', 'b', 'hello from dealer socket']) 

------------ 
iex(2)> is_binary('a') 
false 
iex(3)> is_binary('hello from dealer socket') 
false 

,否則我看不到太多的代碼和示例代碼是在丘馬克的回購之間的差異。

+1

不錯。我剛剛測試過使用:chumak.send_multipart(sock2,[<<1, 2>>,<<3, 4>>],並且工作正常。所以基本上我有一個類型錯誤。我想我需要使用_erlang二進制文件_通過單引號機制,但實際上將採取包括例如[「123」,「456」]的Elixir二進制文件。真棒。 –