Erlang で echo server
gen_tcp の練習で echo server 書いてみたより
誰か添削してくれないかなぁ…
ということなので,わたしならこう書く,というものを以下に.
添削というほどのことは無理ですが,自分の練習を兼ねて…(^^;
-module(echoserver2). -export([start/0, handle_connection/1, recv_loop/1]).start() ->
{ok, ListenSocket} = gen_tcp:listen(8080,
[{active, false}, binary, {packet, line}, {reuseaddr, true}]),
accept(ListenSocket).accept(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(?MODULE, handle_connection, [Socket]),
accept(ListenSocket).handle_connection(Socket) ->
gen_tcp:send(Socket, <<"hello\r\n">>),
recv_loop(Socket).recv_loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, B} ->
case B of
<<"bye\r\n">> ->
gen_tcp:send(Socket, <<"cya\r\n">>),
gen_tcp:close(Socket);
Other ->
gen_tcp:send(Socket, Other),
recv_loop(Socket)
end;
{error, closed} ->
ok
end.
※見た目のために全角スペース入り.
以下修正点など.
・そもそもの仕様がよくわからないのだけど,echoサーバなら,1行入れるたびに応答が返ってくるもの,という想定にした.
元のコードでは,手元の環境では何も入力せずに改行をした場合に,それまでの応答が返ってきていた.
また,byeを入れても終了しなかった.
(たぶんパケットの切れ目が環境によって異なるためと思う)
・listen では,reuseaddr しておいた方が何かと良いと思うので,追加.
reuseaddr していないと,一度止めて再度起動したときに,ポートが使用中で listen に失敗することがある.
・1行単位での入出力さえあれば十分と思うので,listen には {packet, line} オプションを渡した.
これで,入力は1行単位になるので,recv_loop の受信処理でパケット境界を気にしなくて済む.
※ただし,1行が長すぎると途中で切れるので,その点では注意が必要
・spawnするときのモジュール名は ?MODULE マクロを使うように.
後でモジュールの名前を変える時に余計な手間を省くことが出来る.
The comments to this entry are closed.
Comments
態々ありがとうございます!
とても勉強になります m(_ _)m
Posted by: cooldaemon | Saturday, June 16, 2007 09:07 PM