这都是在headers函数中进行的,还是看mochiweb_http模块的代码:
-
headers(Socket, Request, Headers, HttpLoop, HeaderCount) ->
-
case gen_tcp:recv(Socket, 0, ?IDLE_TIMEOUT) of
-
{ok, http_eoh} ->
-
inet:setopts(Socket, [{packet, raw}]),
-
% 将Socket连接、HTTP请求信息(路径、请求方法、HTTP版本)以及请求消息头列表打包成参数化模块(mochiweb_request)的实例对象
-
Req = mochiweb:new_request({Socket, Request,
-
lists:reverse(Headers)}),
-
HttpLoop(Req), % 让用户编写的函数处理HTTP请求
-
case Req:should_close() of
-
true ->
-
gen_tcp:close(Socket),
-
exit(normal);
-
false ->
-
Req:cleanup(),
-
mochiweb_http:loop(Socket, HttpLoop)
-
end;
-
{ok, {http_header, _, Name, _, Value}} ->
-
headers(Socket, Request, [{Name, Value} | Headers],HttpLoop,
-
1 + HeaderCount);
-
_Other ->
-
gen_tcp:close(Socket),
-
exit(normal)
-
end.
以上处理逻辑都被重新包装到新函数Loop(又一个函数对象),这一包装过程是在mochiweb_http:parse_options函数中进行的。新的Loop函数对象将作为OTP gen_server模块mochiweb_socket_server的运行状态(State)的一部分(这个OTP server模块被mochiweb_http启动,Loop函数对象作为启动参数之一传给mochiweb_socket_server,进入模块的State)
三、接受HTTP请求
作为Mochiweb HTTP Web服务器的核心,mochiweb_socket_server模块负责处理浏览器的HTTP连接(本质上还是socket连接)。
该OTP模块在初始时(init(…)函数)打开trap_exit使服务器进程成为系统进程,并开始在端口监听网络连接,同时,启动(spawn_link)一个HTTP请求接收进程,这个进程执行的是acceptor_loop(…)函数。acceptor_loop接收一个三元tuple作为参数,tuple参数的第一个元素是mochiweb_socket_server服务器进程Pid,第二个是在网络端口进行监听的监听器,第三个就是前面提到的包装好的Loop函数对象,如下:
-
acceptor_loop({Server, Listen, Loop}) ->
-
case catch gen_tcp:accept(Listen) of
-
{ok, Socket} ->
-
gen_server:cast(Server, {accepted, self()}),
-
call_loop(Loop, Socket);
-
{error, closed} ->
-
exit({error, closed});
-
Other ->
-
error_logger:error_report(
-
[{application, mochiweb},
-
"Accept failed error",
-
lists:flatten(io_lib:format("~p", [Other]))]),
-
exit({error, accept_failed})
-
end.
当HTTP请求接收进程收到一个浏览器HTTP连接请求后,先以“发送后不管”的方式(即cast)发accepted消息通知mochiweb_socket_server服务器:有HTTP请求来啦,本进程已接受并负责处理。随后该进程就会调用用户定制的函数对象处理请求。进程是在call_loop函数中执行上述的Loop函数对象
call_loop(Loop, Socket) ->
Loop(Socket).
这个在服务器初始阶段启动的HTTP请求接收进程的Pid被作为mochiweb_socket_server状态的一部分保持在State记录的acceptor字段。mochiweb_socket_server服务器进程的状态还记录了Mochiweb服务器当前能处理的最大连接数(max),每当收到HTTP请求接收进程发过来的一个accepted消息,就减少一个最大连接数,同时,除非当前最大连接数为零,再生成一个新的HTTP请求接收进程,并将mochiweb_socket_server服务器进程的运行状态(State)的acceptor字段替换成这个新的HTTP请求接收进程Pid。这就是Mochiweb接受HTTP请求的策略,有点像自动步枪,尽管枪膛里只有一发子弹,但每射出一发子弹,火药爆炸带来的一部分气体压力自动的将新的子弹压入枪膛,于是就可以连续不断的射击了。
总结
服务器端的业务逻辑在一个函数中实现,然后这个函数像数据对象那样嵌入到Mochiweb中,这是典型的函数式程序设计。这个函数通过mochiweb_request实例对象获取请求的相关信息,并将响应通过该对象发送给客户端浏览器。
每个HTTP请求由一个Erlang进程负责处理,充分发挥了Erlang多线程的优势。一个连接对应一个Erlang进程,比较适合comet这样的应用,并发请求的处理能力与Erlang线程数量正相关。相关测试见A Million-user Comet Application with Mochiweb 。
Mochiweb的实现大量使用了参数化模块的特性,包括核心的代表HTTP请求的mochiweb_request实例对象,某种程度上使Mochiweb有了基于对象(Object-based)的特点。不过参数化模块还是“undocumented and unsupported”,可能在未来版本的Erlang中有一定不兼容风险,但是如果Mochiweb用的人足够多,应用足够广,我想将来的Erlang说不定反受Mochiweb应用的影响,官方确定参数化模块这一特性呢。
mochiweb这类的轻量级Web服务器小巧灵活,它的Web应用不能像JSP、ASP那样方便的写服务器端代码,也没有很多重型Web服务器常见的功能,但胜在易于理解,又足够快。比较适合纯动态内容生成的Web应用,如comet。可以作为现有Web服务器的补充。Facebook就用它做了Web在线聊天。
分享到:
相关推荐
mochiweb实现的web服务器简单实例
erlang mochiweb-test demo .zip
MochiWeb 的最新版本可在MochiWeb 的邮件列表位于 设置 MochiWeb 环境需要 Erlang OTP,可在使用项目创建一个新的 mochiweb:make app PROJECT=project_name 要使用特定目录中的项目创建新的 mochiweb: make app ...
用erlang语言写的,基于mochiweb的聊天室代码
MochiWeb的邮件列表位于 R12B兼容性:MochiWeb的母版已通过R14A及更高版本进行了测试。 与R12B兼容的分支在单独维护。为方便起见,该存储库的R12B分支有时会在官方存储库中进行镜像。 要使用项目创建新的mochiweb,...
RPSSL彗星 RPSSL-Rock-Paper-Scissors-Spock-Lizard是一款简单但着名的2人游戏。 通常,它是第一人称自己玩的,但这是网络版本。 ... ... 因为它使用的资源很少,所以我们可以使其永远处于阻塞状态,并保持连接处于打开...
Webmachine 是一个应用层,为 mochiweb 提供 HTTP 语义的特性,定义一个简单而清晰的连接应用的方式。 标签:Webmachine Web框架
它目前支持Cowboy,Inet,Mochiweb,Webmachine和Yaws。 SimpleBridge用作两个最受欢迎的Erlang Web框架到Web服务器的桥梁: 和 从某种意义上讲,它类似于 ,除了具有一些关键的改进/不同之处: 轻松扩展-需要...
专为高质量和工业用例而设计。 -Tsung是适用于各种协议(包括HTTP,XMPP,LDAP等)的高性能基准框架。 -Lisp风味Erlang(LFE) -Erlang Web MVC,现在具有Comet功能 -MochiWeb是用于构建轻量级HTTP服务器的Erlang库...
heroku-genfsmAn experimental Erlang app which deployed on HerokuSome Deploy Detail在 Heroku 上部署 Webmachine + Mochiweb + ErlyDTL 组合的 Erlang Web 应用
核心功能目的:高性能协议中继端点:WebSocket,MQTT,TCP 代码库:700 LOC(Erlang),500 LOC(JavaScript) 透析仪:REBAR,REBAR3,MAD,MIX 主机:COWBOY,EMQ,MOCHIWEB,RING,TCP,UDP协议扩展模板:DTL,...
erlang web frame
Webmachine是一个应用程序层,它在mochiweb提供的出色的按位和HTTP语法管理的基础上增加了HTTP语义意识,并提供了一种简单明了的方式将其连接到应用程序的行为。 可获得更多信息。 您还可以阅读有关Webmachine的...
很棒的网络刮板 支持 令人敬畏的Web scaper,爬虫的集合。 Java ...开源Web爬虫,建立在nosql数据库(apacheouchdb,riak),AMQP数据库(rabbitmq),webmachine和mochiweb之上。 Python scrap