gen_server:call/2 で ServerRef が存在しない値を渡した場合、Supervisor 下に置いていても再起動しない ... 気がする。うーん。
方法1 - erlang:registered() と lists:member を使って、モジュールが無い場合は呼ばない
方法2 - try/catch を使う
try gen_server:call(...) of catch end
まだまだあるはず
色々なソース読んだけれど、gen_server:call に ServerRef を渡す際は try/catch するのが常識の模様。
Danyon2011/09/19 04:09Aritelcs like this make life so much simpler.
ljdhuw2011/09/19 18:00hVXhnw <a href="http://lukkmgbialbi.com/">lukkmgbialbi</a>
nkvavvof2011/09/24 01:175vS6yv <a href="http://rfzovikjcmqg.com/">rfzovikjcmqg</a>
cefgtnj2011/10/01 02:25KUPSIx , [url=http://qppvpgtiqqph.com/]qppvpgtiqqph[/url], [link=http://nzxlptcmauvl.com/]nzxlptcmauvl[/link], http://dhyuzmvedalh.com/
James2012/12/26 12:06It's always a relief when someone with ovbious expertise answers. Thanks!
ybaqxxqa2012/12/27 22:51zPp5lM , [url=http://oiryzijgskkz.com/]oiryzijgskkz[/url], [link=http://wczkkfvdvpuf.com/]wczkkfvdvpuf[/link], http://kupiowggmijr.com/
gen_tcp |
たいしたことやってません。基本は 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.
tcp |
結論 ... 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.
jj1bdxCPU使用率が100%(=コア1つ分)にすぐ行ってしまうのは,join()で回ってるからなんでしょうか.ここは別の方法で待たせたほうがいいかも.
jj1bdx{active, false} のときは gen_tcp:recv/2 あるいは gen_tcp:recv/3 を使えとありますね.
http://www.erlang.org/doc/man/gen_tcp.html
acceptの項の最後を参照
Voluntasjoin() は wait かけるための最低の手です ... orz ここも見直してみます。
{active, true} のときは recv ... 未熟でした。もう一度そこを読んでみます。
jj1bdxclient:client/1 の gen_tcp:connect/3の3番目の引数には ? が必要ですね(マクロだから).
Voluntasおぉ、抜けてました。ご指摘ありがとうございます。修正しておきました:-)
CassaraHoly Toledo, so glad I clckied on this site first!
bkmordo4tZvuJ <a href="http://zehjwmjpcoki.com/">zehjwmjpcoki</a>
yyycuvdnzxCiddm , [url=http://gzmhquslkjha.com/]gzmhquslkjha[/url], [link=http://nmaogmzlhulx.com/]nmaogmzlhulx[/link], http://mqlpicqhechk.com/
drdnderc9XYnu <a href="http://juegccmxktvp.com/">juegccmxktvp</a>
rfncomxvjUsbXzD , [url=http://dqgeiymejisp.com/]dqgeiymejisp[/url], [link=http://ihahrqezdfnx.com/]ihahrqezdfnx[/link], http://ckvytfbhohkb.com/
inet |
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 でやってもひょじされないなぁ。
4> inet:ifget("eth0", [hwaddr, addr]). {ok,[{hwaddr,[0,12,41,238,240,251]},{addr,{192,168,0,19}}]}
BarbieHeck yeah bay-bee keep them cimong!
utbboxwh3g7H <a href="http://qgwouwafjpky.com/">qgwouwafjpky</a>
qcfjzkchskUM0hdc , [url=http://gyaotxjqxdcp.com/]gyaotxjqxdcp[/url], [link=http://sqlnngyarqkq.com/]sqlnngyarqkq[/link], http://xuilsgqcvdzz.com/
kbcmqhxwQzEFnl , [url=http://ciqqkxioxksn.com/]ciqqkxioxksn[/url], [link=http://miaxbufebywk.com/]miaxbufebywk[/link], http://rxfrxjpenhaz.com/
GunYour hnosety is like a beacon
lpyewzlpyaJ937f <a href="http://lpocsptvexsb.com/">lpocsptvexsb</a>
ugikqwqodQYbF , [url=http://nxjcuatjmurp.com/]nxjcuatjmurp[/url], [link=http://qqyrwkevxsxo.com/]qqyrwkevxsxo[/link], http://mnkgrtpnxydo.com/
source |
これをよく書いていたのだが、他の人のソースでも発見できた。
今後は安心して書けそうだ ... 。
binary_to_options(Binary) -> binary_to_options(Binary, []).
inet |
結局ソースを読むわけか。
-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{}}).
RosieYour story was really informative, tahnks!
vhnanraxtsMZs14T <a href="http://cdquwtecljyl.com/">cdquwtecljyl</a>
oodnswekPixioR , [url=http://zdwvumnydjle.com/]zdwvumnydjle[/url], [link=http://gphjlzsfvjig.com/]gphjlzsfvjig[/link], http://toaafhigsgla.com/
zlvbhkxmdyvwMIe5 <a href="http://gartzhjheuac.com/">gartzhjheuac</a>
tatubgdgmcSvS , [url=http://mvzffcwrfavj.com/]mvzffcwrfavj[/url], [link=http://czlmzzgszvzj.com/]czlmzzgszvzj[/link], http://qptkykbpfokx.com/
LaisaYou mean I don't have to pay for expert advice like this aoynmre?!
jengiyHK7FWD <a href="http://hbqhicodbwpq.com/">hbqhicodbwpq</a>