ボム君.com

読者です 読者をやめる 読者になる 読者になる

Masa's blog

今まで学んできたITスキルを主に。

Erlang: 簡単なサーバーとクライアントのメッセージプログラム

Erlangプログラミングではよく使う二つ以上の間でのメッセージ交換。
主に並行処理で必要不可欠の基礎ポイントをここで。
その簡単な例を作ってみた。

まずモジュールの名前をexample

-module(example).

関数を定義する。ここでは三つの関数を使うので三つとも定義する必要がある。関数名のあとの数字はパラメーターの数をあらわす。

-module(example).
-export([main/0,server/0,client/2]).

ではまずMain関数から。新しいプロセスを作ることと、

-module(example).
-export([main/0,server/0,client/2]).

main() ->
    Server_function = spawn(fun server/0), %サーバーと言う関数をfunと名付け、Spawnを生成し、そのリターン値をServer_functionと名付ける
    spawn(example,client,[Server_function,1]), %Spawnでは上の書き方以外に、Spawn(モジュール名、関数名、 [その関数を呼ぶ際のパラメーター]spawn(example,client,[Server_function,2]),
    spawn(example,client,[Server_function,3]),
    spawn(example,client,[Server_function,4]).

ここで重要ポイントがSpawn関数。以下がその使い方。
Pid = spawn(Fun)
Pid2 = spawn(mymodule, myfun, [Arg1, Arg2, ...])
Pid3 = spawn(OtherMachine, Fun)
Pid4 = spawn(OtherMachine, mymodule, myfun, [Arg1, Arg2, ...])

では次にServer関数を作る。これはサーバー上で何をするかを決める。

ここではシンプルに受け取った全てのメッセージをサーバーは表示させるだけにする。

-module(example).
-export([main/0,server/0,client/2]).

main() ->
    Server_function = spawn(fun server/0), %サーバーと言う関数をfunと名付け、Spawnを生成し、そのリターン値をServer_functionと名付ける
    spawn(example,client,[Server_function,1]), %Spawnでは上の書き方以外に、Spawn(モジュール名、関数名、 [その関数を呼ぶ際のパラメーター]spawn(example,client,[Server_function,2]),
    spawn(example,client,[Server_function,3]),
    spawn(example,client,[Server_function,4]).

server() ->
    receive({Pid,msg,N}) ->
	    io:format("received from ~w ~b~n",[Pid,N]),
	    server()
    end.

クライアントはどうやってサーバーにメッセージを送るか。

メッセージの送信の仕方は、

Pid ! Message

Spawnのリターン値であるプロセス識別子と!と送りたいメッセージを記す。

ではクライアント側の関数を作る。クライアントは何をするかと言うと、

Main関数で生成された四つのプロセスをサーバーに送り出すこと。
ただそれだけ。

-module(example).
-export([main/0,server/0,client/2]).

main() ->
    Server_function = spawn(fun server/0), %サーバーと言う関数をfunと名付け、Spawnを生成し、そのリターン値をServer_functionと名付ける
    spawn(example,client,[Server_function,1]), %Spawnでは上の書き方以外に、Spawn(モジュール名、関数名、 [その関数を呼ぶ際のパラメーター]spawn(example,client,[Server_function,2]),
    spawn(example,client,[Server_function,3]),
    spawn(example,client,[Server_function,4]).

server() ->
    receive({Pid,msg,N}) ->
	    io:format("received from ~w ~b~n",[Pid,N]),
	    server()
    end.
dofor(I,F) ->
    if I > 0 ->
	    F(),
	    dofor(I-1,F);
       true -> done
    end.

client(S,N) ->
    dofor(5, fun() ->%
		     timer:sleep(100),
		     S!{self(),msg,N},
		     done
	     end).

上のdofor関数はただループするためだけのもの。一つ一つのプロセスをループし、サーバーに送る役割。

おしまい。