mochiweb 源码阅读(八)
看来昨天的大雨给北京确实带来了重创,早上出门去海淀驾校,北清路辛庄桥路段直接就堵死了,结果好不容易慢慢走到红绿灯那,才发现前方正抽水,封路了。唉,晚上回到家,上微博发现此次因灾遇难者37人,愿逝者安息!什么时候政府才能拿我们纳税人的钱办点正事,别整天搞形象工程了,来北京那么多年了,每次大雨都没能引起重视,也别搞什么引咎辞职了,直接抓了判刑吧。唉,牢骚发的有点多了,还是继续我们的主题吧,继续跟大家分享mochiweb源码。
在上一篇最后,我们提到mochiweb_http:start/1函数,其中就一行代码,如下:
start(Options) ->mochiweb_socket_server:start(parse_options(Options)).
其中mochiweb_http:parse_options/1 函数我们在上一篇,已经详细分析了,这一篇,我们来看下函数 mochiweb_socket_server:start/1 代码如下:
start(Options) ->case lists:keytake(link, 1, Options) of{value, {_Key, false}, Options1} ->start_server(start, parse_options(Options1));_ ->%% TODO: https://github.com/mochi/mochiweb/issues/58%% [X] Phase 1: Add new APIs (Sep 2011)%% [_] Phase 2: Add deprecation warning%% [_] Phase 3: Change default to {link, false} and ignore link%% [_] Phase 4: Add deprecation warning for {link, _} option%% [_] Phase 5: Remove support for {link, _} option start_link(Options)end.
这里:
< Options = [{loop,{mochiweb_http,loop,
[#Fun<mochiweb_example_web.0.8815963>]}},
{name,mochiweb_example_web},
{ip,{0,0,0,0}},
{port,8080}]
首先,我们看下系统函数:lists:keytake/3,erlang doc地址:http://www.erlang.org/doc/man/lists.html#keytake-3,截图如下:
中文注释版本,参考:erlang lists 系列函数功能与用法详解(共68个函数),截图如下:
知道这个函数的作用,我们就能从上下文知道,如果Options列表中含有配置{link, false},则这里调用第一个分支:start_server(start, parse_options(Options1)),Options1为移除{link, false}选项后的Options列表,否则调用第二个分支:start_link(Options),函数代码如下:
start_link(Options) ->start_server(start_link, parse_options(Options)).
现在我们来做个对比:
如果Options列表中含有配置{link, false},则调用:start_server(start, parse_options(Options1));
如果Options列表中含有配置{link, true},或者不含有该配置(这里我们可以理解为默认配置),则调用:start_server(start_link, parse_options(Options));
那么我们看下mochiweb_socket_server:start_server/2函数的具体实现:
start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) ->ok = prep_ssl(Ssl),case Name ofundefined ->gen_server:F(?MODULE, State, []);_ ->gen_server:F(Name, ?MODULE, State, [])end.
这里F的值为start或start_link,现在大家对Options列表中是否含有link,且值是否为true是否有进一步的理解。其实这里很简单,该选项决定了以什么方式调用gen_server,如果你现在还对gen_server一无所知,建议你移步这里Gen_Server行为,希望你看完这个能对gen_server有所了解,这里也同时推荐《Erlang/OTP并发编程实战》这本书,目前我还没有看完,刚看到第二章,收获还是不少的。
好了,有个函数差点漏了,我们看下 mochiweb_socket_server:parse_options/1 这个函数,完整代码如下:
parse_options(State=#mochiweb_socket_server{}) ->State; parse_options(Options) ->parse_options(Options, #mochiweb_socket_server{}).
这里,如果配置为记录mochiweb_socket_server,则调用第一个分支,返回该配置。否则调用第二个分支,调用函数mochiweb_socket_server:parse_options/2传递Options为第一个参数,#mochiweb_socket_server{}记录为第二个参数,这个记录定义如下:
-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(),profile_fun=undefined}).
函数:mochiweb_socket_server:parse_options/2 完整代码如下:
parse_options([], State) ->State; parse_options([{name, L} | Rest], State) when is_list(L) ->Name = {local, list_to_atom(L)},parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, A} | Rest], State) when A =:= undefined ->parse_options(Rest, State#mochiweb_socket_server{name=A}); parse_options([{name, A} | Rest], State) when is_atom(A) ->Name = {local, A},parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{name, Name} | Rest], State) ->parse_options(Rest, State#mochiweb_socket_server{name=Name}); parse_options([{port, L} | Rest], State) when is_list(L) ->Port = list_to_integer(L),parse_options(Rest, State#mochiweb_socket_server{port=Port}); parse_options([{port, Port} | Rest], State) ->parse_options(Rest, State#mochiweb_socket_server{port=Port}); parse_options([{ip, Ip} | Rest], State) ->ParsedIp = case Ip ofany ->any;Ip when is_tuple(Ip) ->Ip;Ip when is_list(Ip) ->{ok, IpTuple} = inet_parse:address(Ip),IpTupleend,parse_options(Rest, State#mochiweb_socket_server{ip=ParsedIp}); parse_options([{loop, Loop} | Rest], State) ->parse_options(Rest, State#mochiweb_socket_server{loop=Loop}); parse_options([{backlog, Backlog} | Rest], State) ->parse_options(Rest, State#mochiweb_socket_server{backlog=Backlog}); parse_options([{nodelay, NoDelay} | Rest], State) ->parse_options(Rest, State#mochiweb_socket_server{nodelay=NoDelay}); parse_options([{acceptor_pool_size, Max} | Rest], State) ->MaxInt = ensure_int(Max),parse_options(Rest,State#mochiweb_socket_server{acceptor_pool_size=MaxInt}); parse_options([{max, Max} | Rest], State) ->error_logger:info_report([{warning, "TODO: max is currently unsupported"},{max, Max}]),MaxInt = ensure_int(Max),parse_options(Rest, State#mochiweb_socket_server{max=MaxInt}); parse_options([{ssl, Ssl} | Rest], State) when is_boolean(Ssl) ->parse_options(Rest, State#mochiweb_socket_server{ssl=Ssl}); parse_options([{ssl_opts, SslOpts} | Rest], State) when is_list(SslOpts) ->SslOpts1 = [{ssl_imp, new} | proplists:delete(ssl_imp, SslOpts)],parse_options(Rest, State#mochiweb_socket_server{ssl_opts=SslOpts1}); parse_options([{profile_fun, ProfileFun} | Rest], State) when is_function(ProfileFun) ->parse_options(Rest, State#mochiweb_socket_server{profile_fun=ProfileFun}).
从具体的函数逻辑来看,其实这个函数也很简单,就是分别去匹配Options中的每个配置项,然后按照一定格式去存储到记录#mochiweb_socket_server{}中,详细的逻辑我就不一行行跟大家分析了。如果这里你遇到什么地方不理解,欢迎大家留言跟我交流。
我们回到mochiweb_socket_server:start_server/2函数详细分析下:
start_server(F, State=#mochiweb_socket_server{ssl=Ssl, name=Name}) ->ok = prep_ssl(Ssl),case Name ofundefined ->gen_server:F(?MODULE, State, []);_ ->gen_server:F(Name, ?MODULE, State, [])end.
第一行,调用函数:mochiweb_socket_server:prep_ssl/1,完整代码如下:
prep_ssl(true) ->ok = mochiweb:ensure_started(crypto),ok = mochiweb:ensure_started(public_key),ok = mochiweb:ensure_started(ssl); prep_ssl(false) ->ok.
这里仅仅是判断配置项中是否使用SSL协议,关于这个协议,参考维基百科:安全套接层(Secure Sockets Layer,SSL),如果使用ssl,则对应启动这三个应用。
第二行,判断配置项中是否存在name定义,如果存则,则使用该名字作为gen_server的名称,否则不使用名称注册该gen_server。
当启动这个gen_server,最后会调用:mochiweb_socket_server:init/1函数,完整代码如下:
init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog, nodelay=NoDelay}) ->process_flag(trap_exit, true),BaseOpts = [binary,{reuseaddr, true},{packet, 0},{backlog, Backlog},{recbuf, ?RECBUF_SIZE},{active, false},{nodelay, NoDelay}],Opts = case Ip ofany ->case ipv6_supported() of % IPv4, and IPv6 if supportedtrue -> [inet, inet6 | BaseOpts];_ -> BaseOptsend;{_, _, _, _} -> % IPv4[inet, {ip, Ip} | BaseOpts];{_, _, _, _, _, _, _, _} -> % IPv6[inet6, {ip, Ip} | BaseOpts]end,listen(Port, Opts, State).
好了,这一篇就到这里,谢谢大家的耐心阅读,下一篇,我们就从这个函数继续和大家分享mochiweb源码。
明天还要继续练车,大家早点休息,好梦。
转载于:https://www.cnblogs.com/yourihua/archive/2012/07/23/2604264.html
mochiweb 源码阅读(八)相关推荐
- mybatis源码阅读(八) ---Interceptor了解一下
转载自 mybatis源码阅读(八) ---Interceptor了解一下 1 Intercetor MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis允许 ...
- 源码阅读:AFNetworking(八)——AFAutoPurgingImageCache
该文章阅读的AFNetworking的版本为3.2.0. AFAutoPurgingImageCache该类是用来管理内存中图片的缓存. 1.接口文件 1.1.AFImageCache协议 这个协议定 ...
- Soul网关源码阅读(八)路由匹配初探
Soul网关源码阅读(八)路由匹配初探 简介 今日看看路由的匹配相关代码,查看HTTP的DividePlugin匹配 示例运行 使用HTTP的示例,运行Soul-Admin,Sou ...
- 【vn.py学习笔记(八)】vn.py utility、BarGenerator、ArrayManager源码阅读
[vn.py学习笔记(八)]vn.py utility.BarGenerator.ArrayManager源码阅读 写在前面 1 工具函数 2 BarGenerator 2.1 update_tick ...
- 源码阅读:AFNetworking(十六)——UIWebView+AFNetworking
该文章阅读的AFNetworking的版本为3.2.0. 这个分类提供了对请求周期进行控制的方法,包括进度监控.成功和失败的回调. 1.接口文件 1.1.属性 /**网络会话管理者对象*/ @prop ...
- 源码阅读:SDWebImage(六)——SDWebImageCoderHelper
该文章阅读的SDWebImage的版本为4.3.3. 这个类提供了四个方法,这四个方法可分为两类,一类是动图处理,一类是图像方向处理. 1.私有函数 先来看一下这个类里的两个函数 /**这个函数是计算 ...
- 源码阅读:SDWebImage(十九)——UIImage+ForceDecode/UIImage+GIF/UIImage+MultiFormat
该文章阅读的SDWebImage的版本为4.3.3. 由于这几个分类都是UIImage的分类,并且内容相对较少,就写在一篇文章中. 1.UIImage+ForceDecode 这个分类为UIImage ...
- 超像素SLIC算法源码阅读
超像素SLIC算法源码阅读 超像素SLIC算法源码阅读 SLIC简介 源码阅读 实验结果 其他超像素算法对比 超像素SLIC算法源码阅读 SLIC简介 SLIC的全称Simple Linear Ite ...
- TiDB 源码阅读系列文章(十六)INSERT 语句详解
在之前的一篇文章 <TiDB 源码阅读系列文章(四)INSERT 语句概览> 中,我们已经介绍了 INSERT 语句的大体流程.为什么需要为 INSERT 单独再写一篇?因为在 TiDB ...
最新文章
- MyBatis常见面试题汇总
- js_jQuery综合机试练习题
- java 方法 示例_Java集合syncedSortedSet()方法与示例
- 数据结构探险系列—栈篇-学习笔记
- mongodb数据库的备份与恢复
- 性能测试小总结(四) 结果分析(未完成)
- 如何合理的配置线程数?
- RecyclerView(四)设置分割线样式(Android 5.0 新特性)
- Git部署远程仓库至github
- python中函数参数*args和**kw的区别
- etcd工作原理和部署指南
- 计算机输入输出接口是交接界面,计算机组成原理试题1
- 华为四核处理器K3V2
- 模块二、添加Customer 类
- Windows安全加固简介
- 可以同情弱者,别同情弱势!
- 英语——长难句分析及技巧
- 计算机网络发展的第四阶段特点,计算机网络基础考试重点.doc
- win7matlab2016启动闪退,大白菜修复win7系统启动matlab出现闪退的图文方案
- 进程管理API之find_get_pid
热门文章
- python【Multiprocessing and threading】深入浅出多进程和多线程
- 【Network Security!】服务器远程管理
- 基础算法 —— 贪心算法
- c++ 多重背包状态转移方程_背包问题之零钱兑换
- 网络推广外包浅析当下网站优化处于健康状态有利于网络推广外包
- java 重定向到某个页面并弹出消息_Java开发面试宝典之网络通信篇
- 芯片如何储存信息_机器视觉检测设备相机的分辨率是如何定义的怎么分类?
- mac r 导出csv文件_每天学习一点R:8.数据的导入和输出
- 开发日记-20190914 关键词 汇编语言王爽版 第四章
- 开发日记-20190821 关键词 读书笔记《掌控习惯》DAY 1