Mochiweb是一个框架,在你用它来生成一个你"指定名字(Name)"项目前(下载源码,然后这样来生成你的项目:make app PROJECT=project_name PREFIX=$HOME/projects/),它是什么都不做的。
假设你生成的是name项目。
就会在你的项目里自动生成下面的文件:name.erl, name_app.erl, name_sup.erl, name_deps.erl, name.app等
然后入口在,你的name.erl的start/0,然后里面最后会调用application:start(name)。就是会用这个配置文件:name.app,启动整个项目(标准的OTP gen_server框架:name.app, name_app.erl, name_sup.erl, name_web.erl)。然后,就是name_app.erl,然后再是name_sup.erl(在这里可以配置你的mochiweb server的参数,例如,IP,Port等)。然后就是name_web.erl。
然后,你的逻辑就加在name_web.erl里面的loop/2里面。当一个接到一个请求,loop/2就会被执行一次。
其实,在name_web.erl里面,第一个被调用的fun是start/1。这里就是mochiweb自己的入口。
start(Options) ->
{DocRoot, Options1} = get_option(docroot, Options),
Loop = fun (Req) ->
?MODULE:loop(Req, DocRoot)
end,
mochiweb_http:start([{name, ?MODULE}, {loop, Loop} | Options1]).
这里把name_web.erl的loop当一个Param传给mochiweb_http。
-define(DEFAULTS, [{name, ?MODULE},
{port, 8888}]).
parse_options(Options) ->
{loop, HttpLoop} = proplists:lookup(loop, Options),
Loop = fun (S) ->
?MODULE:loop(S, HttpLoop)
end,
Options1 = [{loop, Loop} | proplists:delete(loop, Options)],
mochilists:set_defaults(?DEFAULTS, Options1). %%看看,DEFAULT的属性Options1里有没有,没有的话就设置成DEFAULT,有就保留原样。
...
start() ->
start([{ip, "127.0.0.1"},
{loop, {?MODULE, default_body}}]).
start(Options) ->
mochiweb_socket_server:start(parse_options(Options)).
然后,就是mochiweb_socket_server了。又是一个OTP的gen_server(所以才叫socket_server)。先调用start/1,然后就是start_server/1
-record(mochiweb_socket_server,
{port,
loop,
name=undefined,
%% NOTE: This is currently ignored.
max=2048,
ip=any,
listen=null,
nodelay=false,
backlog=128,
active_sockets=0,
acceptor_pool_size=16,
ssl=false,
ssl_opts=[{ssl_imp, new}],
acceptor_pool=sets:new()}).
start(State=#mochiweb_socket_server{}) ->
start_server(State);
start(Options) ->
start(parse_options(Options)).
...
start_server(State=#mochiweb_socket_server{ssl=Ssl, name=Name}) ->
case Ssl of
true ->
application:start(crypto),
application:start(ssl);
false ->
void
end,
case Name of
undefined ->
gen_server:start_link(?MODULE, State, []);
_ ->
gen_server:start_link(Name, ?MODULE, State, [])
end.
注意了,从name_sup.erl调用开始,一直都是函数调用,在start_server/1里面,调用gen_server:start_link/3or/4后,这个叫Name的gen_server就成为supervisor name_sup的一个worker了!
哈哈,大家知道这个时候Name里面是什么吗?在默认的情况下?
………………
恩恩,聪明的同学已经看到了,就是"name_web"。这里mochiweb框架很好地嫁接了,项目的处理逻辑和本身mochiweb的supervisor-worker的关系。
今天累了,以后有时间继续……