gen_tcp のお勉強。

簡易 jabber サーバを書くためにも、gen_tcp のお勉強をする。

  • gen_tcp:listen

待ち受け。

listen(Port, Options) -> {ok, ListenSocket} | {error, Reason}

Options は [binary, {packet, PacketType}, {active, true}, {reuseaddr, true}] といったところ。

{active, true} にした場合はデータを受信するたびに {tcp, Socket, Data} を送ってくる。{tcp_closed, Socket} もセットで。

  • gen_tcp:accept

来たら反応

accept(ListenSocket) -> {ok, Socket} | {error, Reason}
  • gen_tcp:recv

返す

recv(Socket, Length) -> {ok, Packet} | {error, Reason}
  • gen_tcp:close

閉じる

close(Socket) -> ok | {error, Reason}

ブロッキングとノンブロッキングのいいとこ取り

{active, once} にするとおいしいらしい、
複数のクライアントから接続を受け付けるが、アクティブになるのはひとつだけで、
iinet:setopts(Socket, [{active, once}]). を呼び出さない限り次の処理へと行く。

UDP ばかりで、TCP のお作法がまだよくわかっていないが、{active, true} でノンブロッキングでいい気がするけどどうなんだろう。

実際の並列化した TCP サーバ

プログラミング Erlang パクリまくり。
今週中には見ないで書けるようになる予定。

% vim: sw=4 sts=4

-module(echo_tcp).
-compile(export_all).

parallel_server() ->
    {ok, Listen} = gen_tcp:listen(12345, [binary,
                                         {packet, 4},
                                         {active, true},
                                         {reuseaddr, true}]),
    spawn(fun() -> par_connect(Listen) end).

par_connect(Listen) ->
    receive
        {ok, Socket} ->
            gen_tcp:accept(Listen),
            spawn(fun() -> par_connect(Listen) end),
            loop(Socket)
    end.

loop(Socket) ->
    receive
        {tcp, Socket, Data} ->
            case gen_tcp:send(Socket, Data) of
                ok ->
                    ok,
                    loop(Socket);
                {error, _} ->
                    error
            end;
        {tcp_closed, Socket} ->
            tcp_closed
    end.

眠いときにエントリー書いてはいけない

ソース間違いまくりじゃん。
ソース修正しました。