Goal
- gen_udpの簡単なサンプルを実装する
Dev-Environment
- OS: Windows8.1
- Erlang: Eshell V7.3, OTP-Version 18.3
- Elixir: v1.2.3
Using gen_udp module in elixir
gen_udpを使ってみたいと思います。
pingと文字列を渡して、pongと文字列を返すだけの簡単なサンプルの実装になります。
(ローカルホスト内で行っています)
pingと文字列を渡して、pongと文字列を返すだけの簡単なサンプルの実装になります。
(ローカルホスト内で行っています)
gen_udp module sample
コネクションレスなUDPを使ってサーバとクライアントで通信を取ってみましょう。
全体の処理における流れは以下のようになります。
全体の処理における流れは以下のようになります。
- [server]:gen_udp.open/2でUDPソケットをオープンにする。
- [client]:gen_udp.open/2でUDPソケットをオープンにする。
- [client]:gen_udp.send/4でサーバへデータを送信する。
- [server]クライアント側からのデータを受信し処理する。
- [server]:gen_udp.send/4でクライアント側へデータを送信する。
- [client]サーバ側からのデータを受信し処理する。(応答が確実ではないのでタイムアウトを設定しています)
- [client]:gen_udp.close/1でソケットを閉じる。
ざっと処理を書いていくとこんな感じになります。
サーバの実装は以下のようになります。
サーバの実装は以下のようになります。
File: simple_udp_server.ex
defmodule SimpleUdpServer do
def start_server do
{:ok, socket} = :gen_udp.open(1234, [:binary])
loop
end
defp loop do
receive do
{:udp, socket, host, port, bin} ->
:io.format("server receive binary = ~p~n", [bin])
str = :erlang.binary_to_term(bin)
:io.format("server unpacked = ~p~n", [str])
:gen_udp.send(socket, host, port, :erlang.term_to_binary('pong'))
loop
end
end
end
次は、クライアントの実装になります。
File: simple_udp_client.ex
defmodule SimpleUdpClient do
def ping do
{:ok, socket} = :gen_udp.open(4321, [:binary])
:ok = :gen_udp.send(socket, 'localhost', 1234,
String.to_char_list("ping") |> :erlang.term_to_binary)
value = receive do
{:udp, _socket, _, _, bin} ->
:io.format("Client received binary = ~p~n", [bin])
str = :erlang.binary_to_term(bin)
:io.format("Client result = ~p~n", [str])
{:ok, str}
after
2_000 -> :error
end
:gen_udp.close(socket)
value
end
end
gen_tcpと同じく注意点としては、バイナリでやり取りしているのでバイナリへ変換していることと、
stringではなく、char_listで送っている点です。
またgen_tcpと違って、”socket closed”のメッセージを受け取ることを考えなくてよい。
stringではなく、char_listで送っている点です。
またgen_tcpと違って、”socket closed”のメッセージを受け取ることを考えなくてよい。
実行してみましょう。ターミナルが二つ必要になります。
Example:
- ターミナル1(Server)
iex> SimpleUdpServer.start_server
...
# ターミナル2を実行すると下記のように出力される
server receive binary = <<131,107,0,4,112,105,110,103>>
server unpacked = "ping"
- ターミナル2(Client)
iex> SimpleUdpClient.ping
Client received binary = <<131,107,0,4,112,111,110,103>>
Client result = "pong"
{:ok, 'pong'}
Note:
こっちもinetモジュールを使って色々とアクセス元の情報を取得できる。