学习完erlang的基本语法,发觉这门语言的语法还算简单,要掌握的东西并不多,有几点感悟:模式匹配实在是太好用了,无全局变量、不能修改变量这两条似乎处处制约着编写程序。
Talk is cheap,show me the code
简单的双人聊天室
这里需要三个角色:user1,user2,server。
user需要2个操作:send,recv。
程序分析
1 |
|
难点
1 |
|
解决
1 |
|
1 |
|
1 |
|
但是这又引入了新的问题,handle不能空转,它需要user给它指示。
erlang自带的消息功能将派上大用场。
1 |
|
每一个进程都有自己的信箱,只有匹配的信件才会被取出。利用信箱来完成消息的同步,就能实现以聊天功能了。顺便模仿一下gen_server的写法。其主要特点有:1.使用behaviour模式,使得灵活地创建各类模块;2.用一个结构化变量来存储所需的数据。
下面给出完整代码:
s_gen_server.erl:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53%%%-------------------------------------------------------------------
%%% @author PC
%%% @copyright (C) 2016, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 15. 涓冩湀 2016 10:04
%%%-------------------------------------------------------------------
-module(s_gen_server).
-author("PC").
%% API
-export([call/2, terminate/1, main/1]).
%% behaviour
-export([start_link/2, behaviour_info/1, handle/1, init/2]).
%%-spec init(Arg)->{ok,state}|{error,Reason}.
%%-spec handle_call(Request,From,State) -> {ok,new_state}|{error,Reason}.
%%-spec start_link(Module, Args)->Result.
%%Result={ok,Pid}.
behaviour_info(callbacks) ->
[{init, 1},
{handle_call, 3}];
behaviour_info(_Other) ->
undefined.
handle(State) ->
receive
{Module, From, Request} ->
case Module:handle_call(Request, From, State) of
{_Type, _State} -> From ! {_Type, _State}, handle(_State)
end;
stop ->
receive
Bagger -> io:format("~p~n", [Bagger])
after
1 -> finish
end
end.
%%API
start_link(Module, Args) ->
Pid=spawn(?MODULE, init, [Module, Args]),
register(Module,Pid).
init(Module, Args) ->
{ok, State} = Module:init(Args),
handle(State).
call(Module, Request) ->
Module ! {Module, self(), Request},
receive
{noreply, _State} -> ok;
{reply, State} -> State
end.
terminate(Module) ->
Module ! stop.
main(_T) ->
start_link(chat, "chat_center").
chat_server.erl:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39%%%-------------------------------------------------------------------
%%% @author PC
%%% @copyright (C) 2016, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 15. 涓冩湀 2016 10:23
%%%-------------------------------------------------------------------
-module(chat_server).
-author("PC").
-behaviour(s_gen_server).
%% history=[Msg::{who,string()}]
-record(state, {history = [], remain = [], servername}).
-export([init/1, handle_call/3]).
%% API
-export([start_link/0, recv/0, send/2,stop/0,show_history/0]).
start_link() ->
s_gen_server:start_link(?MODULE, "chat_center").
send(Who, Word) ->
s_gen_server:call(?MODULE, {send, Who, Word}).
show_history() ->
State = s_gen_server:call(?MODULE, fetch),
State#state.history.
stop() ->
s_gen_server:terminate(?MODULE).
-spec recv() -> #state{} .
recv() ->
State = s_gen_server:call(?MODULE, fetch),
s_gen_server:call(?MODULE, {update, State#state{remain = [], history = State#state.history ++ [State#state.remain]}}),
State#state.remain.
%% behaviour
init(_Arg) ->
{ok, #state{servername = _Arg}}.
handle_call({send, Who, String}, _From, State) ->
{noreply, #state{remain = State#state.remain ++ [{Who, String}]}};
handle_call(fetch, _From, State) ->
{reply, State};
handle_call({update, NewState}, _From, _) ->
{noreply, NewState}.