Hatena::Grouperlang

Erlang Mind

2009-05-29

gen_server:call/2

| 01:10

gen_server:call/2 で ServerRef が存在しない値を渡した場合、Supervisor 下に置いていても再起動しない ... 気がする。うーん。

追記

方法1 - erlang:registered() と lists:member を使って、モジュールが無い場合は呼ばない

方法2 - try/catch を使う

try gen_server:call(...) of
catch
end

まだまだあるはず

追記2

色々なソース読んだけれど、gen_server:call に ServerRef を渡す際は try/catch するのが常識の模様。

DanyonDanyon2011/09/19 04:09Aritelcs like this make life so much simpler.

ljdhuwljdhuw2011/09/19 18:00hVXhnw <a href="http://lukkmgbialbi.com/">lukkmgbialbi</a>

nkvavvofnkvavvof2011/09/24 01:175vS6yv <a href="http://rfzovikjcmqg.com/">rfzovikjcmqg</a>

cefgtnjcefgtnj2011/10/01 02:25KUPSIx , [url=http://qppvpgtiqqph.com/]qppvpgtiqqph[/url], [link=http://nzxlptcmauvl.com/]nzxlptcmauvl[/link], http://dhyuzmvedalh.com/

JamesJames2012/12/26 12:06It's always a relief when someone with ovbious expertise answers. Thanks!

ybaqxxqaybaqxxqa2012/12/27 22:51zPp5lM , [url=http://oiryzijgskkz.com/]oiryzijgskkz[/url], [link=http://wczkkfvdvpuf.com/]wczkkfvdvpuf[/link], http://kupiowggmijr.com/

2009-01-05

勉強になるコード

| 14:08

なるほどなぁ ... 。

Count = 10,
lists:foreach(fun(_) ->
                ...
              end,
              lists:duplicate(Count, dummy)).

YthhyYthhy2012/12/26 10:51I love these artclies. How many words can a wordsmith smith?

2009-01-03

動きました。

| 05:04

たいしたことやってません。基本は gen_tcp の example です。それに gen_tcp:controlling_process を使って accept で生成したソケットを別プロセスに渡しています。

これの問題は無限のプロセスを生成してしまうことでしょうか。 connect に after でタイムアウト処理を付ければ上手くいくのかな。

基本の基で突っかかってるあたり未熟だなぁと実感させられました。

-module(tcp_echo_server).
-compile(export_all).

-define(kOptions, [{active, false}, binary, {packet, 2}]).
-define(kMaxAcceptors, 5).

start() ->
  case gen_tcp:listen(5000, ?kOptions) of
    {ok, ListenSocket} ->
      start_acceptors(?kMaxAcceptors, ListenSocket),
      {ok, Port} = inet:port(ListenSocket),
      Port;
    {error, _Reason} ->
      error
  end.

start_acceptors(0, _) ->
  ok;
start_acceptors(Num, ListenSocket) ->
  Pid = spawn(fun() -> acceptor(ListenSocket) end),
  io:format("acceptor: ~p:~p\n", [Num, Pid]),
  start_acceptors(Num-1, ListenSocket).

acceptor(ListenSocket) ->
  case gen_tcp:accept(ListenSocket) of
    {ok, Socket} ->
      io:format("accept: ~p\n", [self()]),
      Pid = spawn(fun() -> connect(Socket) end),
      gen_tcp:controlling_process(Socket, Pid),
      acceptor(ListenSocket);
    {error, _Reason} ->
      acceptor(ListenSocket)
  end.

connect(Socket) ->
  inet:setopts(Socket, [{active, once}]),
  receive
    {tcp, Socket, Packet} ->
      io:format("tcp: ~p\n", [Packet]),
      gen_tcp:send(Socket, Packet),
      connect(Socket);
    {tcp_closed, Socket} ->
      io:format("tcp_closed: ~p\n", [self()]),
      ok = gen_tcp:close(Socket);
    {tcp_error, Socket, _Reason} ->
      io:format("tcp_error: ~p\n", [self()]),
      ok = gen_tcp:close(Socket)
  end.

くらいあんと(コピペだけど)

-module(client).
-compile(export_all).

-define(kOptions, [{active,false}, binary, {packet,2}]).

client(Message) ->
  {ok, Sock} = gen_tcp:connect("localhost", 5000, ?kOptions),
  gen_tcp:send(Sock,Message),
  A = gen_tcp:recv(Sock, 0),
  gen_tcp:close(Sock),
  A.

2009 年は TCP のお勉強から。

| 23:13

結論 ... TCP は難しい。

やりたいことはプロセスプールを作っておいてそれぞれが gen_tcp:accept 状態にしておく。

これは R11B-3 から一つの待ち受けソケットに対して複数の Erlang プロセスから gen_tcp:accept が呼び出すことが出来るようになったから。

そして、 accept して出来た新しいソケットを別プロセスに渡してもう一度 accept 状態にする。

ということがやりたいのだけれど、どーもうまくいかない、書き方間違ってるんだろうなぁ。

ちなみに accept 後に使うプロセスは使い捨て。accept に使うプロセスはすーぱーばいざーにでも面倒を見させておくのが理想型。

Erlang 的な TCP サーバの回答は個人的にこれだと思うんだけどなぁ。最初に起動しておくプロセスは自由に設定できると幸せに慣れそう。

まだまだ初心者のレベルにも到達してないな。

あ、ちなみに動きません。Accept するところまでは行くんですが送受信が上手いこと言ってません。

-module(tcp_echo_server).
-compile(export_all).

-define(MAX_ACCEPTOR, 5).

start_link() ->
  spawn(fun() -> init() end).

init() ->
  case gen_tcp:listen(
    5000, [{active, true}, binary, {packet, line}, {reuseaddr, true}]
  ) of
    {ok, ListenSocket} ->
      loop(ListenSocket);
    {error, _Reason} ->
      error
  end,
  receive
    {ok} ->
      ok
  end.

stop() ->
  ok.

loop(ListenSocket) ->
  loop(ListenSocket, 0).
loop(_ListenSocket, ?MAX_ACCEPTOR) ->
  ok;
loop(ListenSocket, Count) ->
  Pid = spawn(fun() -> accept(ListenSocket) end),
  io:format("loop: ~p, ~p\n", [Count, Pid]),
  loop(ListenSocket, Count + 1).

accept(ListenSocket) ->
  case gen_tcp:accept(ListenSocket) of
    {ok, Socket} ->
      io:format("accept: ~p\n", [self()]),
      spawn(fun() -> connect(Socket) end),
      accept(ListenSocket);
    {error, _Reason} ->
      accept(ListenSocket)
  end.

connect(Socket) ->
  receive
    {tcp, Socket, Packet} ->
      io:format("~p\n", [Packet]),
      case gen_tcp:send(Socket, [Packet]) of
        ok ->
          connect(Socket);
        {error, _Reason} ->
          io:format("error: ~p\n", [self()]),
          ok = gen_tcp:close(Socket)
      end;
    {tcp_closed, Socket} ->
      io:format("tcp_closed: ~p\n", [self()]),
      ok = gen_tcp:close(Socket);
    {tcp_error, Socket, _Reason} ->
      io:format("tcp_error: ~p\n", [self()]),
      ok = gen_tcp:close(Socket)
  end.

追記

  • 力武さんからのつっこみにより、{active, true} にしてみた。最終的には {active, once} に成るのだろうが、今は簡単なエコーサーバなので {active, true} でよし。
  • join で無理矢理待たせていたのを receive で待たせました。

jj1bdxjj1bdx2009/01/03 23:36CPU使用率が100%(=コア1つ分)にすぐ行ってしまうのは,join()で回ってるからなんでしょうか.ここは別の方法で待たせたほうがいいかも.

jj1bdxjj1bdx2009/01/03 23:45{active, false} のときは gen_tcp:recv/2 あるいは gen_tcp:recv/3 を使えとありますね.
http://www.erlang.org/doc/man/gen_tcp.html
acceptの項の最後を参照

VoluntasVoluntas2009/01/04 03:18join() は wait かけるための最低の手です ... orz ここも見直してみます。
{active, true} のときは recv ... 未熟でした。もう一度そこを読んでみます。

jj1bdxjj1bdx2009/01/04 08:37client:client/1 の gen_tcp:connect/3の3番目の引数には ? が必要ですね(マクロだから).

VoluntasVoluntas2009/01/04 16:42おぉ、抜けてました。ご指摘ありがとうございます。修正しておきました:-)

CassaraCassara2012/10/08 20:54Holy Toledo, so glad I clckied on this site first!

bkmordobkmordo2012/10/09 05:574tZvuJ <a href="http://zehjwmjpcoki.com/">zehjwmjpcoki</a>

yyycuvdnzyyycuvdnz2012/10/10 07:58xCiddm , [url=http://gzmhquslkjha.com/]gzmhquslkjha[/url], [link=http://nmaogmzlhulx.com/]nmaogmzlhulx[/link], http://mqlpicqhechk.com/

drdnderdrdnder2012/10/11 14:08c9XYnu <a href="http://juegccmxktvp.com/">juegccmxktvp</a>

rfncomxvjrfncomxvj2012/10/12 03:31UsbXzD , [url=http://dqgeiymejisp.com/]dqgeiymejisp[/url], [link=http://ihahrqezdfnx.com/]ihahrqezdfnx[/link], http://ckvytfbhohkb.com/

2008-05-25

MACアドレス

| 14:54

inet:getif() returns all the IP addresses
inet:getiflist() returns all the network devices
inet:ifget("eth0", [hwaddr, addr]) returns the MAC and IP addrs

hwaddr でやってもひょじされないなぁ。

2009/02/01

4> inet:ifget("eth0", [hwaddr, addr]).
{ok,[{hwaddr,[0,12,41,238,240,251]},{addr,{192,168,0,19}}]}

BarbieBarbie2011/09/18 18:40Heck yeah bay-bee keep them cimong!

utbboxutbbox2011/09/19 02:01wh3g7H <a href="http://qgwouwafjpky.com/">qgwouwafjpky</a>

qcfjzkchskqcfjzkchsk2011/09/19 22:40UM0hdc , [url=http://gyaotxjqxdcp.com/]gyaotxjqxdcp[/url], [link=http://sqlnngyarqkq.com/]sqlnngyarqkq[/link], http://xuilsgqcvdzz.com/

kbcmqhxwkbcmqhxw2011/10/01 02:32QzEFnl , [url=http://ciqqkxioxksn.com/]ciqqkxioxksn[/url], [link=http://miaxbufebywk.com/]miaxbufebywk[/link], http://rxfrxjpenhaz.com/

GunGun2012/12/26 12:11Your hnosety is like a beacon

lpyewzlpylpyewzlpy2012/12/27 15:18aJ937f <a href="http://lpocsptvexsb.com/">lpocsptvexsb</a>

ugikqwqugikqwq2012/12/27 22:54odQYbF , [url=http://nxjcuatjmurp.com/]nxjcuatjmurp[/url], [link=http://qqyrwkevxsxo.com/]qqyrwkevxsxo[/link], http://mnkgrtpnxydo.com/

2008-05-24

安心した

| 01:51

これをよく書いていたのだが、他の人のソースでも発見できた。

今後は安心して書けそうだ ... 。

binary_to_options(Binary) ->                                                    
    binary_to_options(Binary, []).

set_opt

| 01:06

結局ソースを読むわけか。

-type(socket_setopt() ::
      {'raw', non_neg_integer(), non_neg_integer(), binary()} |
      %% TCP/UDP options
      {'reuseaddr',       bool()} |
      {'keepalive',       bool()} |
      {'dontroute',       bool()} |
      {'linger',          {bool(), non_neg_integer()}} |
      {'broadcast',       bool()} |
      {'sndbuf',          non_neg_integer()} |
      {'recbuf',          non_neg_integer()} |
      {'priority',        non_neg_integer()} |
      {'tos',             non_neg_integer()} |
      {'nodelay',         bool()} |
      {'multicast_ttl',   non_neg_integer()} |
      {'multicast_loop',  bool()} |
      {'multicast_if',    ip_address()} |
      {'add_membership',  {ip_address(), ip_address()}} |
      {'drop_membership', {ip_address(), ip_address()}} |
      {'header',          non_neg_integer()} |
      {'buffer',          non_neg_integer()} |
      {'active',          bool() | 'once'} |
      {'packet',        
       0 | 1 | 2 | 4 | 'raw' | 'sunrm' |  'asn1' |
       'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph'} |
      {'mode',           list() | binary()} |
      {'port',           'port', 'term'} |
      {'exit_on_close',   bool()} |
      {'low_watermark',   non_neg_integer()} |
      {'high_watermark',  non_neg_integer()} |
      {'bit8',            'clear' | 'set' | 'on' | 'off'} |
      {'send_timeout',    non_neg_integer() | 'infinity'} |
      {'delay_send',      bool()} |
      {'packet_size',     non_neg_integer()} |
      {'read_packets',    non_neg_integer()} |
      %% SCTP options
      {'sctp_rtoinfo',               #sctp_rtoinfo{}} |
      {'sctp_associnfo',             #sctp_assocparams{}} |
      {'sctp_initmsg',               #sctp_initmsg{}} |
      {'sctp_nodelay',               bool()} |
      {'sctp_autoclose',             non_neg_integer()} |
      {'sctp_disable_fragments',     bool()} |
      {'sctp_i_want_mapped_v4_addr', bool()} |
      {'sctp_maxseg',                non_neg_integer()} |
      {'sctp_primary_addr',          #sctp_prim{}} |
      {'sctp_set_peer_primary_addr', #sctp_setpeerprim{}} |
      {'sctp_adaptation_layer',      #sctp_setadaptation{}} |
      {'sctp_peer_addr_params',      #sctp_paddrparams{}} |
      {'sctp_default_send_param',    #sctp_sndrcvinfo{}} |
      {'sctp_events',                #sctp_event_subscribe{}} |
      {'sctp_delayed_ack_time',      #sctp_assoc_value{}}).

RosieRosie2011/09/18 06:01Your story was really informative, tahnks!

vhnanraxtsvhnanraxts2011/09/18 16:44MZs14T <a href="http://cdquwtecljyl.com/">cdquwtecljyl</a>

oodnswekoodnswek2011/09/19 18:46PixioR , [url=http://zdwvumnydjle.com/]zdwvumnydjle[/url], [link=http://gphjlzsfvjig.com/]gphjlzsfvjig[/link], http://toaafhigsgla.com/

zlvbhkxmdyzlvbhkxmdy2011/09/20 02:02vwMIe5 <a href="http://gartzhjheuac.com/">gartzhjheuac</a>

tatubgdtatubgd2011/09/27 01:53gmcSvS , [url=http://mvzffcwrfavj.com/]mvzffcwrfavj[/url], [link=http://czlmzzgszvzj.com/]czlmzzgszvzj[/link], http://qptkykbpfokx.com/

LaisaLaisa2012/08/24 16:42You mean I don't have to pay for expert advice like this aoynmre?!

jengiyjengiy2012/08/25 15:32HK7FWD <a href="http://hbqhicodbwpq.com/">hbqhicodbwpq</a>