gen_tcp の練習で echo server 書いてみた

-module(echoserver).
-export([start/0, handle_connection/1, recv_loop/2]).

start() ->
    {ok, ListenSocket} = gen_tcp:listen(8080, [{active, false}, binary]),
    io:fwrite("listen~n"),
    accept(ListenSocket).

accept(ListenSocket) ->
    {ok, Socket} = gen_tcp:accept(ListenSocket),
    io:fwrite("accept~n"),
    Pid = spawn(echoserver, handle_connection, [Socket]),
    io:fwrite("spawn ~w~n", [Pid]),
    accept(ListenSocket).

handle_connection(Socket) ->
    gen_tcp:send(Socket, "hello\r\n"),
    recv_loop(Socket, []).

recv_loop(Socket, Bs) ->
    case gen_tcp:recv(Socket, 0) of
        {ok, B} ->
            case B of
                <<"\r\n">> ->
                    case list_to_binary(Bs) of
                        <<"bye">> ->
                            gen_tcp:send(Socket, "cya\r\n"),
                            gen_tcp:close(Socket),
                            io:fwrite("bye~n");
                        Other ->
                            gen_tcp:send(Socket, Other),
                            gen_tcp:send(Socket, "\r\n"),
                            io:fwrite("send~n"),
                            recv_loop(Socket, [])
                    end;
                _ ->
                    io:fwrite("B :~p~n", [B]),
                    io:fwrite("Bs:~s~n", [Bs]),
                    recv_loop(Socket, [Bs, B])
            end;        
        {error, closed} ->
            io:fwrite("close~n")
    end.

誰か添削してくれないかなぁ…

添削してもらえた!

大感謝!本当にありがとうございます!
みかログ: Erlang で echo server

仕様は、下記を考えておりました。

  • 8080 で listen
  • accept 後は、プロセスを分ける事で、client からの接続を複数受け付ける
  • CRLF が入力されるまで入力を受け付ける
  • CRLF が入力されると、それまで入力された文字列を echo する
  • bye が入力されると切断される

添削結果を拝見させて頂いて、次回以降、気をつけようと思った箇所のまとめ

  • gen_tcp:listen のオプションに {reuseaddr, true} を指定する事
  • gen_tcp:listen のオプションには、{packet, line} もあって便利(一行が長すぎると切れる場合もある ←要調査)
  • gen_tcp:listen のオプションに binary を指定した場合は、gen_tcp:send の第二引数に binary を設定する事
  • 文字列より binary の方が小メモリで扱う場合に高速である為、binary を優先的に使う事
  • ?MODULE マクロで、モジュール名が取得できる(spawn や gen_server:call とかで使う)
  • プロセスの終了時に ok を返しておく

早く仕事に使えるくらい精通したい