直接来看cowboy_http:loop/1, State 的主要参数:
parent :: 不重要 ref :: http socket :: 不重要 transport :: ranch_tcp opts = #{ connection_type => supervisor, env => #{dispatch => [{'_',[],[{[],[],toppage_h,[]}]}]} }, peer = {{127,0,0,1},52467} , sock = {{127,0,0,1},8080}, timer = 定时器的ref, active = true , %%套接字的类型,true为主的接收,上一篇博客的最后有介绍 in_streamid = 3, %%还不知道用来干嘛 flow = 65535, out_streamid = 3, %%还不知道用来干嘛 out_state = wait :: wait | chunked | streaming | done, last_streamid = 100,%%还不知道用来干嘛 streams = [] :: [stream()]当收到一个Http的get请求时,会执行parse -> parse_request -> after_parse。 其中parse 和 parse_request是在处理一些请求的解析、参数的解析,后续深入了解的时候再看。递归、模式匹配跳来跳去的有点难懂。
主要看 after_parse ,after_parse的第一条,会执行cowboy_stream:init/3,在cowboy_stream:init/3中会执行对应的流处理程序。 注意!你写的get方法就是从这里开始执行的!
默认的流处理模块是cowboy_stream_h,cowboy_stream_h会再执行中间件,默认的中间件是cowboy_router、cowboy_handler,中间件会新开一个进程去执行。(todo 这里是坑,我还不知道中间件是干嘛用的)
新开的进程会执行到我们自己写的toppage_h的init函数,执行完成之后会执行 cowboy_req:reply/4进行回复,回复会回复到cowboy_http所在的进程,与loop函数中的 {{Pid, StreamID}, Msg} 匹配上,匹配上之后会执行info/1函数,最后在commands中匹配到response,返回给浏览器。
疑问点的地方其实挺多了,只是梳理了一下调用链,函数为什么这么设计完全没看懂。包括StreamID的用法、异步的意义、长连接怎么处理的、什么时候断掉连接,等等一大堆问题。