TCPæ¥ç¶ã®åŠçã¯ãé床ã1ç§ããã1äžãªã¯ãšã¹ãã«è¿ã¥ããšç°¡åã«ããã«ããã¯ã«ãªããŸããå¹ççãªèªã¿åããšæžã蟌ã¿ã¯å¥ã®åé¡ã«ãªããåŠçã³ã¢ã®ã»ãšãã©ã¯ã¢ã€ãã«ç¶æ
ã«ãªããŸãã
ãã®èšäºã§ã¯ãTCPãæäœãã3ã€ã®ã³ã³ããŒãã³ããæ¥ç¶ã®åä¿¡ãã¡ãã»ãŒãžã®åä¿¡ãããã³ããããžã®å¿çãæ¹åããæé©åãææ¡ããŸãã
ãã®èšäºã¯ãErlangããã°ã©ããŒãšãåã«Erlangã«èå³ããã人ã®äž¡æ¹ã察象ãšããŠããŸãã èšèªã®æ·±ãç¥èã¯å¿
èŠãããŸããã
ãTCPã®æäœãã3ã€ã®éšåã«åããŸãã
- æ¥ç¶åãå
¥ã
- ã¡ãã»ãŒãžãåä¿¡ãã
- ã¡ãã»ãŒãžãžã®è¿ä¿¡
ã¿ã¹ã¯ã«ãã£ãŠã¯ããããã®éšåã®ãããããããã«ããã¯ã«ãªãå ŽåããããŸãã
TCPãµãŒãã¹ãäœæããã«ã¯ã
gen_tcpãçŽæ¥äœ¿çšãã
æ¹æ³ãšãæã人æ°ã®ããErlangæ¥ç¶ããŒã«ã©ã€ãã©ãªã§ãã
ranchã䜿çšããæ¹æ³ã®2ã€ãæ€èšããŸãã ææ¡ãããæé©åã®äžéšã¯ãããããã®å Žåã«ã®ã¿é©çšãããŸãã
ããã©ãŒãã³ã¹ã®å€åãè©äŸ¡ããããã«ã
tcp_workerã§MZBenchã䜿çšããŸã
ãtcp_workerã¯ãæ¥ç¶ããã³èŠæ±æ©èœãšåææ©èœãå®è£
ããŸãã 2ã€ã®ã¹ã¯ãªãããfast_connectããšãfast_receiveãã䜿çšãããŸãã 1ã€ç®ã¯é床ãäžããŠæ¥ç¶ãéãã2ã€ç®ã¯æ¢ã«éããŠããæ¥ç¶ã§ã§ããã ãå€ãã®ãã±ãããéä¿¡ããããšããŸãã åã¹ã¯ãªããã¯ãc4.2xlarge AmazonããŒãã§å®è¡ãããŸããã ErlangããŒãžã§ã³ã¯18ã§ãã
MZBenchã®ã¹ã¯ãªãããšé¢æ°ã³ãŒãã¯
GitHubã§å
¥æã§ããŸã ã
æ¥ç¶åãå
¥ã
åžžã«åæ¥ç¶ããã¯ã©ã€ã¢ã³ãã倿°ããå Žåãããšãã°ãã¯ã©ã€ã¢ã³ãããã»ã¹ã®æéãéåžžã«å¶éãããŠããå ŽåããŸãã¯æ°žç¶çãªæ¥ç¶ããµããŒãããŠããªãå Žåã¯ãæ¥ç¶ããã°ããåãå
¥ããããšãéèŠã§ãã
ç§å Žã®æé©å
ç§å Žã䜿çšããTCPãµãŒãã¹ã¯éåžžã«ç°¡åã§ãã
ã©ã³ãã«ä»å±ãããµã³ãã«
ãšã³ãŒãµãŒãã¹ã®ã³ãŒãã倿ŽããŠãçä¿¡ãã±ããã«å¯ŸããŠãokããš
å¿çããããã«ããŸããéãã¯ä»¥äžã®ãšããã§ãã
--- a/examples/tcp_echo/src/echo_protocol.erl +++ b/examples/tcp_echo/src/echo_protocol.erl @@ -16,8 +16,8 @@ init(Ref, Socket, Transport, _Opts = []) -> loop(Socket, Transport) -> case Transport:recv(Socket, 0, 5000) of - {ok, Data} -> - Transport:send(Socket, Data), + {ok, _Data} -> + Transport:send(Socket, <<"ok">>), loop(Socket, Transport); _ -> ok = Transport:close(Socket) --- a/examples/tcp_echo/src/tcp_echo_app.erl +++ b/examples/tcp_echo/src/tcp_echo_app.erl @@ -11,8 +11,8 @@
ãfast_connectãã¹ã¯ãªãããå®è¡ããŠéå§ããŸãïŒæ¥ç¶ãéãé床ãäžããŸãïŒã

å·ŠåŽã®ã°ã©ãã¯ããµã€ãºã214msã®ç°åžžå€ã瀺ããŠããŸããæ®ãã®è¡ã¯ã5ç§ééã«åå²ãããæéé
å»¶ã®ããŒã»ã³ã¿ã€ã«ã«å¯Ÿå¿ããŠããŸãã å³åŽã®ã°ã©ãã¯ãååç©ã®éå°é床ã§ããããšãã°ãæŸé»é åã§ã¯ãæ¯ç§çŽ3.5åååç©ã§ããã ãã®ã·ããªãªã§ã¯ãæ¯å1ã€ã®ã¡ãã»ãŒãžãéä¿¡ããããããã¡ãã»ãŒãžã®æ°ã¯éããŠããæ¥ç¶ã®æ°ã«å¯Ÿå¿ããŸãã
é床ãããã«äžãããšã次ã®çµæãåŸãããŸãã

1000ããªç§ã®æŸåºã¯ã¿ã€ã ã¢ãŠãã«å¯Ÿå¿ããŸãã ååç©ãéãé床ãäžãç¶ãããšãæŸåºãããé »ç¹ã«ãªããŸãã æåã®ã¹ãã€ã¯ã¯5k rpsã§çŸãã11k rpsã§åžžã«ååšããŸãã
ã¿ã€ããŒä»ãã®ãã±ããåä¿¡æã®ã¿ã€ã ã¢ãŠãã眮ãæããïŒsleepïŒïŒ
ã¡ãã»ãŒãžãåä¿¡ããéã®ã¿ã€ã ã¢ãŠããã©ã¡ãŒã¿ã®åçŽãªäŸå€ã«ãããæ¥ç¶ã®ç¢ºç«é床ã倧å¹
ã«åäžããããšãããããŸããã æå€§é床ã§ãœã±ãããããŒãªã³ã°ããªãããã«ãã¿ã€ããŒã远å ããŸããïŒsleepïŒ20ïŒïŒ
--- a/examples/tcp_echo/src/echo_protocol.erl +++ b/examples/tcp_echo/src/echo_protocol.erl @@ -15,10 +15,11 @@ init(Ref, Socket, Transport, _Opts = []) -> loop(Socket, Transport). loop(Socket, Transport) -> - case Transport:recv(Socket, 0, 5000) of - {ok, Data} -> - Transport:send(Socket, Data), + case Transport:recv(Socket, 0, 0) of + {ok, _Data} -> + Transport:send(Socket, <<"ok">>), loop(Socket, Transport); + {error, timeout} -> timer:sleep(20), loop(Socket, Transport); _ -> ok = Transport:close(Socket) end.
ãã®æé©åã«ãããç§å Žã¢ããªã±ãŒã·ã§ã³ã¯ããå€ãã®æŽæ°ãååŸã§ããŸããæåã®æ¥å¢ã¯11k rpsã§ã®ã¿çºçããŸãã

ããã«é床ãäžããããšãããšãæŸåºã¯ããã«å€§ãããªããŸãã ãããã£ãŠãæå€§æ°ã¯24k rpsã§ãã
ãããã«ææ¡ãããæé©åã«ããã11kãã24k rpsã®æ¥ç¶åä¿¡é床ã®çŽ2åã®ã²ã€ã³ãåŸãããŸããã
Gen_tcpã®æé©å
以äžã¯ãç§ãç§å Žã§è¡ã£ãããšã«äŒŒããgen_tcpã䜿çšããã¯ãªãŒã³ãªå®è£
ã§ãïŒããã¹ãã¯ããªããžããªã«
simple.erlãšããŠ
ãµã³ãã«ãçšæãããŠããŸãïŒã
-export([service/1]). -define(Options, [ binary, {backlog, 128}, {active, false}, {buffer, 65536}, {keepalive, true}, {reuseaddr, true} ]). -define(Timeout, 5000). main([Port]) -> {ok, ListenSocket} = gen_tcp:listen(list_to_integer(Port), ?Options), accept(ListenSocket). accept(ListenSocket) -> case gen_tcp:accept(ListenSocket) of {ok, Socket} -> erlang:spawn(?MODULE, service, [Socket]), accept(ListenSocket); {error, closed} -> ok end. service(Socket) -> case gen_tcp:recv(Socket, 0, ?Timeout) of {ok, _Binary} -> gen_tcp:send(Socket, <<"ok">>), service(Socket); _ -> gen_tcp:close(Socket) end.
åãã¹ã¯ãªãããå®è¡ãããšãçµæãåŸãããŸããã

ã芧ã®ãšãããçŽ18k rpsã§æ¥ç¶ã®åä¿¡ãäžå®å®ã«ãªããŸãã ç§ãã¡ã¯ã18kãèŠããããšã倿ãããšä»®å®ããŸãã
ã¿ã€ããŒä»ãã®ãã±ããåä¿¡æã®ã¿ã€ã ã¢ãŠãã眮ãæããïŒsleepïŒïŒ
ç§å Žãšåãæé©åãé©çšããŸãã
service(Socket) -> case gen_tcp:recv(Socket, 0, 0) of {ok, _Binary} -> gen_tcp:send(Socket, <<"ok">>), service(Socket); {error, timeout} -> timer:sleep(20), service(Socket); _ -> gen_tcp:close(Socket) end.
ãã®å Žåã23k rpsãåŠçããŸãïŒ

ãã¹ãããã»ã¹ã®è¿œå
2çªç®ã®ã¢ã€ãã¢ã¯ãæ¥ç¶ãåãå
¥ããããã»ã¹ã®æ°ãå¢ããããšã§ãã ããã¯ãããã€ãã®ããã»ã¹ããgen_tcpïŒacceptãåŒã³åºãããšã§å®çŸã§ããŸãã
main([Port]) -> {ok, ListenSocket} = gen_tcp:listen(list_to_integer(Port), ?Options), erlang:spawn(?MODULE, accept, [ListenSocket]), erlang:spawn(?MODULE, accept, [ListenSocket]), accept(ListenSocket).
è² è·ã®äžã§ãã¹ããããš32k rpsãåŸãããŸãã

è² è·ãããã«å¢å ãããšãé
å»¶ãå¢å ããŸãã
ãããã«gen_tcpã®ã¿ã€ã ã¢ãŠããæé©åãããšãåä¿¡é床ã18kãã23kã«5k rpså¢å ããŸãã
è€æ°ã®ãã¹ãããã»ã¹ãããå Žåãgen_tcpã¯32k rpsãåŠçããŸããããã¯ãæé©åãªãã®å Žåã®1.8åã§ãã
ãŸãšã
- åŒã³åºã颿°ãtimerïŒsleepã®ã¿ã€ã ã¢ãŠããã©ã¡ãŒã¿ã䜿çšããªãããšããå§ãããŸãã ããã¯ç§å ŽãšçŽç²ãªgen_tcpã®äž¡æ¹ã«é©çšãããŸãã ç§å Žã®å Žåãããã¯æ¥ç¶ãåä¿¡ãããé床ã2åã«ããŸãã
- ããã€ãã®ããã»ã¹ã®ãã¡ãæ¥ç¶ã¯ããéãåãå
¥ããããŸãã ããã¯ãçŽç²ãªgen_tcpã«ã®ã¿é©çšãããŸãã ç§ã®å Žåãããã«ãããæ¥ç¶ã®åä¿¡é床ã40ïŒ
åäžããã¿ã€ã ã¢ãŠããã¿ã€ããŒïŒsleepïŒïŒïŒã«çœ®ãæããããŸããã
ã¡ãã»ãŒãžãåä¿¡ãã
ããã¯ããã§ã«ç¢ºç«ãããæ¥ç¶ã§å€æ°ã®ã·ã§ãŒãã¡ãã»ãŒãžãåä¿¡ããæ¹æ³ã®äžéšã§ãã æ°ããæ¥ç¶ãéãããããšã¯ãã£ãã«ãªããããã§ããã ãæ©ãã¡ãã»ãŒãžãèªãã§è¿ä¿¡ããå¿
èŠããããŸãã ãã®ã·ããªãªã¯ãWebãœã±ãããåããããŒãæžã¿ã¢ããªã±ãŒã·ã§ã³ã«å®è£
ãããŸãã
è€æ°ã®ããŒããã25kã®æ¥ç¶ãéããã¡ãã»ãŒãžã®éä¿¡é床ãåŸã
ã«äžããŸãã
ç§å Žã®æé©å
以äžã¯ãç§å Žã䜿çšããæé©åãããŠããªãã³ãŒãã®çµæã§ãïŒå·ŠåŽãæéé
å»¶ãå³åŽãã¡ãã»ãŒãžåŠçé床ïŒã

æé©åãè¡ããªãå Žåãç§å Žã¯æå€§æé800msã§70k rpsãåŠçããŸãã
Linuxãããã¡ãŒãå¢ãã
ããªãäžè¬çãªæé©åã¯ã
Linuxãœã±ãããããã¡ãŒã®å¢å ã§ãã ãã®æé©åãçµæã«ã©ã®ããã«åœ±é¿ããããèŠãŠã¿ãŸãããã
ãããã«ãã®å Žåããããã¡ãå¢ãããŠã倧ããªå©ç¹ã¯ãããŸããã
GET_TCPæé©å
以äžã§ã¯ãåã®èšäºã®gen_tcpãœãªã¥ãŒã·ã§ã³ã§ãã±ããåŠçé床ã確èªããŸããã

ç§å Žã®ããã«70k rpsã
èªã¿åãããã»ã¹ã®æ°ãæžãããŸãã
åã®ã±ãŒã¹ã§ã¯ããœã±ãããã25,000ããã»ã¹ãèªã¿åããŸããïŒæ¥ç¶ããšã«1ããã»ã¹ïŒã 次ã«ããã®æ°ãæžãããŠçµæã確èªããŸãã
100åã®ããã»ã¹ãäœæãããããã®éã«æ°ãããœã±ãããé
åžããŸãã
main([Port]) -> {ok, ListenSocket} = gen_tcp:listen(list_to_integer(Port), ?Options), Readers = [erlang:spawn(?MODULE, reader, []) || _X <- lists:seq(1, ?Readers)], accept(ListenSocket, Readers, []). accept(ListenSocket, [], Reversed) -> accept(ListenSocket, lists:reverse(Reversed), []); accept(ListenSocket, [Reader | Rest], Reversed) -> case gen_tcp:accept(ListenSocket) of {ok, Socket} -> Reader ! Socket, accept(ListenSocket, Rest, [Reader | Reversed]); {error, closed} -> ok end. reader() -> reader([]). read_socket(S) -> case gen_tcp:recv(S, 0, 0) of {ok, _Binary} -> gen_tcp:send(S, <<"ok">>), true; {error, timeout} -> true; _ -> gen_tcp:close(S), false end. reader(Sockets) -> Sockets2 = lists:filter(fun read_socket/1, Sockets), receive S -> reader([S | Sockets2]) after ?SmallTimeout -> reader(Sockets) end.
ãã®æé©åã«ãããããã©ãŒãã³ã¹ã倧å¹
ã«åäžããŸãã

é床ã®åäžã«å ããŠãæéé
å»¶ã¯ã¯ããã«è¯ãèŠããåŠçããããã±ããã®æ°ã¯çŽ100kã§ãããããã«ã120kã®ã¡ãã»ãŒãžã§ãåŠçã§ããŸããã倧ããªæéé
å»¶ããããŸãã æé©åããªããã°ãããã¯ã§ããŸããã§ããã
ãããã«1ã€ã®ããã»ã¹ããè€æ°ã®æ¥ç¶ãåŠçãããšãçŽç²ãªgen_tcpãµãŒããŒã®ããã©ãŒãã³ã¹ãå°ãªããšã50ïŒ
åäžããŸãã
Linuxãããã¡ãŒãå¢ãã
vanilla gen_tcpã¹ã¯ãªããã䜿çšããŠãã·ã¹ãã ã«åãæé©åãé©çšããŸãã

ç§å Žã®å Žåãšåæ§ã«ãéèŠãªçµæã¯è¡šç€ºãããã远å ã®å€ãå€ã®ã¿ã倧ããªæéé
å»¶ã®åœ¢ã§çŸããŸããã
æé©åãæ¢ã«æé©åãããgen_tcpã«é©çšãããšãå€ãã®æéé
å»¶å€ãå€ãåŸãããŸãã
ãããã«çŽç²ãªgen_tcpãœãªã¥ãŒã·ã§ã³ããLinuxãããã¡ãŒã®å¢å ã®æ©æµãåããŸããã ãœã±ããããèªã¿åãããã»ã¹ã®æ°ãæžãããšãåŠçé床ã50ïŒ
åäžããŸãã
ãŸãšã
- æåã¯ãã©ã¡ãã®ãœãªã¥ãŒã·ã§ã³ã§ããã»ãŒåãæ°ã®ã¡ãã»ãŒãžãçŽ70k rpsãåŠçã§ããŸãã
- ãããã¡ã®å¢å ã¯åŠçé床ã®å€§å¹
ãªå¢å ãèš±å¯ãããçŽç²ãªgen_tcpã®å Žåã倧ããªæéé
å»¶ã®åœ¢ã§ãµã³ãã«ã远å ããŸãã
- ããã»ã¹ããšã«è€æ°ã®ãœã±ãããåããGen_tcpãœãªã¥ãŒã·ã§ã³ã¯ãæé©åãããŠããªããœã±ãããããå°ãªããšã1.5åé«éã«å®è¡ãããæéé
å»¶ã倧å¹
ã«æ¹åãããŸãã æ®å¿µãªããããã®æé©åã¯ãã¢ãŒããã¯ãã£ã倿Žããªããšç§å Žã«ã¯é©çšã§ããŸããã
ã¡ãã»ãŒãžãžã®è¿ä¿¡
æ£åŒã«ã¯ãåã®ç« ã§ã¯ãã¡ãã»ãŒãžåŠçãµã€ã¯ã«ã¯ããã«å¯Ÿããçããæ³å®ããŠããŸãããããã®éšåãæé©åããããã®ããšã¯ããŸããã§ããã åãã¢ã€ãã¢ãã¡ãã»ãŒãžéä¿¡æ©èœã«é©çšããŠã¿ãŸãã ããã§ã¯ãåã®ç« ã®ã¹ã¯ãªããã䜿çšããŸãããã®ã¹ã¯ãªããã§ã¯ããã±ããã¯æ¢ã«ç¢ºç«ãããæ¥ç¶ãééããŸãã
ã¿ã€ã ã¢ãŠããšããã»ã¹ã®æé©å
åã®ç« ã§äœ¿çšããã®ãšåãã¢ã€ãã¢ãéä¿¡æ©èœã«é©çšã§ããŸããã¿ã€ã ã¢ãŠããåé€ããããå°ãªãããã»ã¹ããå¿çããŸãã send颿°ã«ã¯ã¿ã€ã ã¢ãŠããªã©ã®ãã©ã¡ãŒã¿ãŒã¯ãããŸãããæ¥ç¶ãéããšãã«{send_timeoutã0}ãªãã·ã§ã³ãèšå®ããå¿
èŠããããŸãã
æ®å¿µãªããããã®æé©åã¯å®éã«ã¯äœã倿Žãããã³ãŒãã倿Žããã ãã§ãªãã·ã§ã³ã远å ããããšã«ãªããŸãããã®ãããèªè
ã«diffãšã°ã©ããç
©ãããªãããšã«ããŸããã
ããã»ã¹æ°ãã©ã®ããã«åœ±é¿ãããã確èªããããã«ã次ã®ã¹ã¯ãªããã䜿çšããŸããã
-export([responder/0, service/2]). -define(Options, [ binary, {backlog, 128}, {active, false}, {buffer, 65536}, {keepalive, true}, {send_timeout, 0}, {reuseaddr, true} ]). -define(SmallTimeout, 50). -define(Timeout, 5000). -define(Responders, 200). main([Port]) -> {ok, ListenSocket} = gen_tcp:listen(list_to_integer(Port), ?Options), Responders = [erlang:spawn(?MODULE, responder, []) || _X <- lists:seq(1, ?Responders)], accept(ListenSocket, Responders, []). accept(ListenSocket, [], Reversed) -> accept(ListenSocket, lists:reverse(Reversed), []); accept(ListenSocket, [Responder | Rest], Reversed) -> case gen_tcp:accept(ListenSocket) of {ok, Socket} -> erlang:spawn(?MODULE, service, [Socket, Responder]), accept(ListenSocket, Rest, [Responder | Reversed]); {error, closed} -> ok end. responder() -> receive S -> gen_tcp:send(S, <<"ok">>), responder() after ?SmallTimeout -> responder() end. service(Socket, Responder) -> case gen_tcp:recv(Socket, 0, ?Timeout) of {ok, _Binary} -> Responder ! Socket, service(Socket, Responder); _ -> gen_tcp:close(Socket) end.
ããã§ã¯ãå¿çããããã»ã¹ãèªè
ãšå
±æãããŸãã 25,000人ã®èªè
ãš200人ã®åçè
ãããŸãã
ãã ãããã®æé©åã§ããåã®ã»ã¯ã·ã§ã³ã®gen_tcpãœãªã¥ãŒã·ã§ã³ãšæ¯èŒããŠã倧å¹
ãªããã©ãŒãã³ã¹ã®åäžã¯èŠãããŸããã

Erlangã®ãã¥ãŒãã³ã°
1ã€ã®ããã»ã¹ã䜿çšããŠè€æ°ã®ãœã±ãããåŠçããå Žåã1ã€ã®äœéãªã¯ã©ã€ã¢ã³ããä»ã®ãã¹ãŠã®ãœã±ããã®é床ãäœäžãããå¯èœæ§ããããŸãã ãã®ç¶æ³ãåé¿ããã«ã¯ããœã±ãããéããšãã«{send_timeoutã0}ãèšå®ãã倱æããå Žåã¯æ¬¡ã®ã«ãŒãã§éä¿¡ãç¹°ãè¿ããŸãã
æ®å¿µãªãããéä¿¡æ©èœã¯éä¿¡ããããã€ãæ°ãè¿ããŸããã POSIXãšã©ãŒã®ã¿ãè¿ãããããã¢ãã ããOKãã§ãã ããã«ãããæ£åžžã«éä¿¡ãããæåŸã®ãã€ãããéä¿¡ã§ããªããªããŸãã ããã«ããã®éãç¥ã£ãŠãããšããããã¯ãŒã¯ãããå¹ççã«äœ¿çšã§ããŸããããã¯ã顧客ã®ãã£ãã«ã貧匱ãªå Žåã«ç¹ã«éèŠã«ãªããŸãã
次ã«ããããä¿®æ£ããæ¹æ³ã®äŸã瀺ããŸãã
- å
¬åŒWebãµã€ãããErlangãœãŒã¹ãããŠã³ããŒãããŸãã
$ wget http://erlang.org/download/otp_src_18.2.1.tar.gz $ tar -xf otp_src_18.2.1.tar.gz $ cd otp_src_18.2.1
- inet erts / emulator / drivers / common / inet_drv.cãã©ã€ããŒé¢æ°ãæŽæ°ããŸãã
- çªå·ã§å¿çããæ©èœã远å ããŸãã
static int inet_reply_ok_int(inet_descriptor* desc, int Val) { ErlDrvTermData spec[2*LOAD_ATOM_CNT + 2*LOAD_PORT_CNT + 2*LOAD_TUPLE_CNT]; ErlDrvTermData caller = desc->caller; int i = 0; i = LOAD_ATOM(spec, i, am_inet_reply); i = LOAD_PORT(spec, i, desc->dport); i = LOAD_ATOM(spec, i, am_ok); i = LOAD_INT(spec, i, Val); i = LOAD_TUPLE(spec, i, 2); i = LOAD_TUPLE(spec, i, 3); ASSERT(i == sizeof(spec)/sizeof(*spec)); desc->caller = 0; return erl_drv_send_term(desc->dport, caller, spec, i); }
- tcp_inet_commandv颿°ãããokããéä¿¡ããã¢ãã ãåé€ããŸãããã
else inet_reply_error(INETP(desc), ENOTCONN); } else if (desc->tcp_add_flags & TCP_ADDF_PENDING_SHUTDOWN) tcp_shutdown_error(desc, EPIPE); >> else tcp_sendv(desc, ev); DEBUGF(("tcp_inet_commandv(%ld) }\r\n", (long)desc->inet.port)); }
- tcp_sendv颿°ã§0ãè¿ã代ããã«ãint sendã远å ããŸãã
default: if (len == 0) >> return inet_reply_ok_int(desc, 0); h_len = 0; break; } ----------------------------------- else if (n == ev->size) { ASSERT(NO_SUBSCRIBERS(&INETP(desc)->empty_out_q_subs)); >> return inet_reply_ok_int(desc, n); } else { DEBUGF(("tcp_sendv(%ld): s=%d, only sent " LLU"/%d of "LLU"/%d bytes/items\r\n", (long)desc->inet.port, desc->inet.s, (llu_t)n, vsize, (llu_t)ev->size, ev->vsize)); } DEBUGF(("tcp_sendv(%ld): s=%d, Send failed, queuing\r\n", (long)desc->inet.port, desc->inet.s)); driver_enqv(ix, ev, n); if (!INETP(desc)->is_ignored) sock_select(INETP(desc),(FD_WRITE|FD_CLOSE), 1); } >> return inet_reply_ok_int(desc, n);
- å®è¡/æ§æ&& make && make installã
ããã§ã颿°gen_tcpïŒsendã¯æåãããš{okãNumber}ãè¿ããŸãã äžèšã®ã³ãŒããã©ã°ã¡ã³ãã¯ã9ããåºåããŸãã
{ok, Sock} = gen_tcp:connect(SomeHostInNet, 5555, [binary, {packet, 0}]), {ok, N} = gen_tcp:send(Sock, "Some Data"), io:format("~p", [N])
ãããã«1ã€ã®ããã»ã¹ããè€æ°ã®æ¥ç¶ãåŠçããå Žåããœã±ããã®äœææã«{send_timeoutã0}ãªãã·ã§ã³ã䜿çšããå¿
èŠããããŸããããããªããšã1ã€ã®äœéã¯ã©ã€ã¢ã³ããä»ã®ãã¹ãŠã®ã¯ã©ã€ã¢ã³ããžã®éä¿¡ãé
ãããå ŽåããããŸãã
ãããã³ã«ãéšåçãªã¡ãã»ãŒãžãåŠçã§ããå ŽåãOTPã«ããããåœãŠãŠãéä¿¡ããããã€ãæ°ãèæ
®ããã®ãæåã§ãã
ç°¡åã«
- æ¥ç¶ããã°ããåãå
¥ããå¿
èŠãããå Žåã¯ãè€æ°ã®ããã»ã¹ããæ¥ç¶ãåãå
¥ããå¿
èŠããããŸãã
- ãœã±ãããããã°ããèªã¿åãå¿
èŠãããå Žåã¯ã1ã€ã®ããã»ã¹ããè€æ°ã®ãœã±ãããåŠçããç§å Žã䜿çšããªãã§ãã ããã
- Linuxãããã¡ãŒãå¢ãããšãã·ã¹ãã ã®å®å®æ§ãäœäžããããã©ãŒãã³ã¹ã倧å¹
ã«åäžããããšã¯ãããŸããã
- 1ã€ã®ããã»ã¹ããè€æ°ã®ãœã±ããã䜿çšããå Žåãéä¿¡ã¿ã€ã ã¢ãŠããåé€ããå¿
èŠããããŸãã
- éä¿¡ãããæ£ç¢ºãªãã€ãæ°ãç¥ãå¿
èŠãããå Žåã¯ãOTPã«ããããé©çšã§ããŸãã
åç
§è³æ