2012年2月22日水曜日

Erlang TCP接続2 HTTPサーバ(超簡易)

TCPの勉強のつづき。

ローカル上でHTTPサーバを立てて、ブラウザで「Hello」と表示する。
C言語で実装したものをErlangでやってみた。

ソースを貼るが、もっとわかりやすいソースがWebにあったので、そちらをまず紹介。
Erlang で httpd - プログラマのネタ帳 : http://d.hatena.ne.jp/shomah4a/20110110/1294634635

下のソースを以下のようにビルドして、実行しよう。

$>C:\Users\andre\ework>erlc http_server.erl
c:/Users/andre/ework/http_server.erl:35: Warning: variable 'Result' is unused

$>C:\Users\andre\ework>erl -noshell -run http_server server -run init stop

◆ソース


-module( http_server ).
-compile( export_all ).

server() ->
    io:format("~p~n", [?LINE]),
    %% TCPクライアントからの接続要求を待てる状態
    { ok, LSock } = gen_tcp:listen( 12345, [ binary, { packet, 0 } ] ),

    io:format("~p~n", [?LINE]),
    Responce = "HTTP/1.0 200 OK\r\n"
               "Content-Length: 20\r\n"
               "Content-Type: text/html\r\n"
               "\r\n"
               "Hello\r\n",
    io:format("~p~n", [?LINE]),

    loop( LSock, Responce ).

do_recv( Sock, Bin ) ->
    io:format("~p~n", [?LINE]),
    receive
        { tcp, Sock, Binary } ->
            { ok, [ Binary | Bin ] };
        { tcp_closed, Sock } ->
            { ok, Bin }
    end.

loop( LSock, Responce ) ->
    %% TCPクライアントからの接続要求を受け付ける
    { ok, ASock } = gen_tcp:accept( LSock ),

    io:format("~p~n", [?LINE]),
    %% 受信
    { ok, Bin } = do_recv( ASock, [] ),
    Result = list_to_binary( lists:reverse( Bin ) ),

    io:format("~p~n", [?LINE]),
    %% 送信
    gen_tcp:send( ASock, Responce ),

    io:format("~p~n", [?LINE]),
    %% TCPセッション終了
    ok = gen_tcp:close( ASock ),

    %% 末尾再帰
    loop( LSock, Responce ).


ブラウザから下記のアドレスにアクセスしよう。
http://localhost:12345/



デバッグのために、標準出力でソースの行数が表示されるのは、申し訳ないです。