You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> A very useful debugging and measurement tool is an echo service. An
> echo service simply sends back to the originating source any data it
> receives.
> デバッグや計測のためにとても便利なツールとしてエコーサービスがある.
> エコーサービスは,受け取ったどんなデータも,単に送信元へと送り返す.
Echo Protocolの種類
TCP Based Echo Service
UDP Based Echo Service
TCP Based Echo Service
> One echo service is defined as a connection based application on TCP.
> A server listens for TCP connections on TCP port 7. Once a
> connection is established any data received is sent back. This
> continues until the calling user terminates the connection.
> 一つめのエコーサービスは,TCP上で接続をベースにしたアプリケーションとして定義されている.
> サーバーはTCP7番ポートでTCP接続を待ち受け(listen)する.
> 接続が確立(established)されたら,どんなデータでも,受け取ったものを送り返す.
> これを呼び出した側のユーザーが接続を切断(terminate)するまで続ける.
# 03-echo.exsdefmoduleEchoServerdodefaccept(port)do:gen_tcp.listen(port,[:binary,packet: :line,active: :false,reuseaddr: true])IO.puts"Accepting connections on port #{port}"endendEchoServer.accept(29297):timer.sleep(:infinity)
待ちうける - 試す
% elixir -r 03-echo.exs
Accepting connections on port 29297
----
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello~
# 06-echo.exsdefmoduleEchoServerdodefaccept(port)do{:ok,socket}=:gen_tcp.listen(port,[:binary,packet: :line,active: :false,reuseaddr: true])IO.puts"Accepting connections on port #{port}"{:ok,client}=:gen_tcp.accept(socket)serve(client)enddefpserve(socket)do{:ok,data}=:gen_tcp.recv(socket,0)
:gen_tcp.send(socket,data)serve(socket)endendEchoServer.accept(29297)
繰り返す - 試す
% elixir -r 06-echo.exs
Accepting connections on port 29297
** (MatchError) no match of right hand side value: {:error, :closed}
06-echo.exs:11: EchoServer.serve/1
(elixir) lib/code.ex:363: Code.require_file/2
(elixir) lib/enum.ex:1088: Enum."-map/2-lists^map/1-0-"/2
----
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello~
hello~
hello again~
hello again~
^]
telnet> quit
Connection closed.
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
# 07-echo.exsdefmoduleEchoServerdodefaccept(port)do{:ok,socket}=:gen_tcp.listen(port,[:binary,packet: :line,active: :false,reuseaddr: true])IO.puts"Accepting connections on port #{port}"{:ok,client}=:gen_tcp.accept(socket)serve(client)enddefpserve(socket)do{:ok,data}=:gen_tcp.recv(socket,0)
:gen_tcp.send(socket,data)serve(socket)endend
% elixir -r 07-echo.exs
Accepting connections on port 29297
Accepting connections on port 29297
20:11:30.728 [error] Task #PID<0.54.0> started from EchoServer.Supervisor terminating** (MatchError) no match of right hand side value: {:error, :closed}
07-echo.exs:11: EchoServer.serve/1
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: &EchoServer.accept/1
Args: [29297]
再接続する - 試す(つづき)
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello~
hello~
hello again~
hello again~
^]
telnet> quit
Connection closed.
/Users/d-kitamura% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello once again~
hello once again~
----
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi!
# 08-echo.exsdefmoduleEchoServerdodefaccept(port)do{:ok,socket}=:gen_tcp.listen(port,[:binary,packet: :line,active: :false,reuseaddr: true])IO.puts"Accepting connections on port #{port}"loop_acceptor(socket)enddefploop_acceptor(socket)do{:ok,client}=:gen_tcp.accept(socket)Task.start_link(fn->serve(client)end)loop_acceptor(socket)enddefpserve(socket)do{:ok,data}=:gen_tcp.recv(socket,0)
:gen_tcp.send(socket,data)serve(socket)endend
% elixir -r 08-echo.exs
Accepting connections on port 29297
Accepting connections on port 29297
20:35:09.005 [error] Task #PID<0.55.0> started from #PID<0.54.0> terminating** (MatchError) no match of right hand side value: {:error, :closed}
08-echo.exs:16: EchoServer.serve/1
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.97146601/0 in EchoServer.loop_acceptor/1>
Args: []
Accepting connections on port 29297
20:35:43.462 [error] Task #PID<0.58.0> started from #PID<0.56.0> terminating** (MatchError) no match of right hand side value: {:error, :closed}
08-echo.exs:16: EchoServer.serve/1
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.97146601/0 in EchoServer.loop_acceptor/1>
Args: []
複数接続する - 試す(つづき)
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello~
hello~
hello again~
hello again~
^]
telnet> quit
Connection closed.
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello once again~
hello once again~
Connection closed by foreign host.
%
----
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi!
hi!
^]
telnet> quit
Connection closed.
% elixir -r 09-echo.exs
Accepting connections on port 29297
20:58:48.775 [error] Task #PID<0.56.0> started from #PID<0.55.0> terminating** (MatchError) no match of right hand side value: {:error, :closed}
09-echo.exs:17: EchoServer.serve/1
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.126567687/0 in EchoServer.loop_acceptor/1>
Args: []
20:59:14.307 [error] Task #PID<0.58.0> started from #PID<0.55.0> terminating** (MatchError) no match of right hand side value: {:error, :closed}
09-echo.exs:17: EchoServer.serve/1
(elixir) lib/task/supervised.ex:89: Task.Supervised.do_apply/2
(stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Function: #Function<0.126567687/0 in EchoServer.loop_acceptor/1>
Args: []
影響を分離する - 試す(つづき)
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello~
hello~
hello again~
hello again~
^]
telnet> quit
Connection closed.
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello once again~
hello once again~
is connected?
is connected?
----
% telnet 127.0.0.1 29297
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi!
hi!
^]
telnet> quit
Connection closed.
影響を分離する
影響を分離できた(あるクライアントでエラーになっても,他のクライアントに影響がない)
エコーサーバー完成
エコーサーバー完成形
defmoduleEchoServerdodefaccept(port)do{:ok,socket}=:gen_tcp.listen(port,[:binary,packet: :line,active: :false,reuseaddr: true])IO.puts"Accepting connections on port #{port}"loop_acceptor(socket)enddefploop_acceptor(socket)do{:ok,client}=:gen_tcp.accept(socket){:ok,pid}=Task.Supervisor.start_child(EchoServer.TaskSupervisor,fn->serve(client)end)
:ok=:gen_tcp.controlling_process(client,pid)loop_acceptor(socket)enddefpserve(socket)do{:ok,data}=:gen_tcp.recv(socket,0)
:gen_tcp.send(socket,data)serve(socket)endendimportSupervisor.Specchildren=[supervisor(Task.Supervisor,[[name: EchoServer.TaskSupervisor]]),worker(Task,[EchoServer,:accept,[29297]])]opts=[strategy: :one_for_one,name: EchoServer.Supervisor]Supervisor.start_link(children,opts)
:timer.sleep(:infinity)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters