Erlang, .
- , gen_server -. - .
- .
- gen_server .
- gen_server. .
- gen_tcp .
- , gen_tcp gen_server.
:
http://erlang.org/doc/design_principles/des_princ.html
6, , , .
, TCP gen_server: handle_info/2 - ? : handle_info
. TCP gen_server. TCP , , . , gen_server: handle_info() . handle_info() , , handle_info().
, TCP, handle_info(). , handle_info(), :
handle_info({tcp, Socket, RawData}, State) ->
Result1 = computerInGermanyProcess(RawData),
Result2 = computerInFranceProcess(RawData),
Result3 = computerInRussiaProcess(RawData),
Result4 = State
gen_tcp:send(Socket, [Result1, Result2, Result3, Result4]),
{noreply, State}; %%Because a TCP message landed in the mailbox with no From value,
%%do not reply to From, and do not mess with the value in State.
computerInGermanyProcess(RawData) ->
%% Possibly use gen_tcp and sockets again to send a message
%% to another computer to get some data in order to
%% calculate Result1:
Result1.
computerInFranceProcess(RawData) ->
...
Result2.
computerInRussiaProcess(RawData) ->
...
Result3.
, , handle_call, handle_cast play - NOR - ( , ). , .
Client:
+------------------------------------------------------+------------------------------------------------------+
| my_request() -> | handle_call({dostuff, Val}, ClientPid, State) -> |
| Request = {dostuff, 10}, | %%Do something with Val, State |
| Server = ?MODULE, | Response = {result, 45}, |
| Response = gen_server:call(Server, Request). | NewState = ...., |
| | | {Response, NewState}. |
| | from gen_server: | |
| | start_link() | ^ |
| | | | | |
+----------------------------+-----------------+-------+-------------------------------------+----------------+
| | |
| | |
+----------------------------+-----------------+-------+ |
|-module(gen_server). | | | |
|-export([call/2,....]). V | | |
| | | |
|call(Server, Request) -> V | |
| Server ! {request, Request, call, self(), Module} --+-->+ |
| receive | | ^
| {reply, Response, Server} -> | | |
| Response ^ | V |
| end. | | | |
+------------------------+-----------------------------+ | |
| Mailbox | | | |
| | | | |
| {reply, Response, Server} <----------<--------+---+--------------<--------------+ |
| | V ^ ^
+------------------------------------------------------+ | | |
| | |
| | |
Server: | | |
+------------------------------------------------------+ | | |
| Mailbox | | | |
| | V ^ ^
| {request, Request, call, ClientPid, Module} <-+---+ | |
| | | | |
+----------------------------+-------------------------+-----------------------------+ | |
| | | | |
|loop(State) -> | | | |
| receive V | ^ ^
| {request, Request, call, ClientPid, Module} -> | | | ^
| {Response, NewState} = Module:handle_call(Request, ClientPid, State} ---+---|-->+ |
| ClientPid ! {reply, Response, self()}, ----------->---------------------+-->+ To Client
| loop(NewState); | ^
| {request, Request, cast, ClientPid, Module} -> | |
| NewState = Module:handle_cast(Request, State), ------->---------->------|----->------------>+
| loop(NewState); |
| ... |
| ... |
| end. |
+------------------------------------------------------------------------------------+
, gen_server:call():
gen_server:start_link(), , , , handle_call/handle_cast.
gen_server:call(ServerName, Request), .
gen_server: (_, ) send a message to the server, :
ServerName ! {request, Request, call, self(), ModName}.
, gen_server: start_link(): - , , handle_call(), handle_cast() ..
, ModName:handle_call(), ModName: handle_call() - :
handle_call(Request, ClientPid, ServerLoopValue) ->
%%Compute some result using information in Request/ServerLoopValue
ModName: handle_call() , a response:
{Response, NewServerLoopValue}.
- :
From ! {reply, Response, ServerPid}.
loop(NewServerLoopValue).
NewServerLoopValue (). loop(), :
loop(ServerLoopValue) ->
receive
{request, dothis, From} ->
Result1 = ...SomeValue + 5....,
From ! {Result1, self()},
loop(NewServerLoopValue);
{request, {dothat, 10}, From} ->
Result2 = ... SomeValue - 10...,
From ! {Result2, self()},
loop(NewServerLoopValue);
{request, stop, From}
%%do not call loop()
end.
ServerLoopValue , . gen_server , ServerLoopValue, ServerLoopValue, .
, gen_server TCP- {active, true}, {packet, 4}:
gen_tcp:send().
Erlang , server mailbox.
{tcp,...} handle_info().
handle_info() gen_tcp:send(Socket, Response), .
handle_info() , loop() :
{noreply, SomeValue} => loop(SomeValue)
, gen_server TCP- {active, false}, {packet, 0}:
Erlang gen_tcp