直接来看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的用法、异步的意义、长连接怎么处理的、什么时候断掉连接,等等一大堆问题。