Mochiweb源代码研究

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的关系。

今天累了,以后有时间继续……

你可能感兴趣的:(框架,Web,erlang,socket)