流程图
DNS解析
- 本地域名服务器查找有没有www.kaola.com所对应的ip
- 本地服务器未查找到,则去根域名服务器查找
- 根域名服务器未找到相应ip,会返回一级域名服务器地址
- 查找一级域名服务器
- 一级域名服务器未找到相应ip,返回二级域名服务器地址
- 查找二级域名服务器
- 二级域名服务器查看本地name.conf,是否有www主机的记录
- 查到www主机的记录,返回www主机的ip到二级域名服务器
- 返回ip到本地域名服务器
- 返回ip到浏览器
http请求
HTTP请求 客户端根据域名获得相应ip之后开始发送http请求,HTTP请求分为三个部分:
TCP三次握手、http请求响应信息、关闭TCP链接html
TCP三次握手
http请求信息
http请求报文 TTP请求报文由请求行(request line)、请求头部(header)、请求主体三个部分组成。以下图所示: nginx
- 请求行包含:请求方法、URL、协议版本 请求方法包含8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。 URL即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成 协议版本即http版本号
- 请求头部包含请求的附加信息,由 名/值 对组成
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中好比:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增长的,使用 keepalive,即持久链接,一个链接能够发多个请求;User-Agent,请求发出者,兼容性以及定制化需求
- 请求主体包含回车符、换行符和请求数据,并非全部请求都具备请求数据
MVC
http请求报文发送后,通过nginx服务器转发、服务端servlet处理请求以后,响应信息会以响应报文的形式返回给客户端。
后续开一章 比较偏后端的mvc整个请求git
http响应信息
响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成。以下图所示: github
- 响应行包含:协议版本,状态码,状态码描述
状态码规则以下:
1xx:指示信息--表示请求已接收,继续处理。
2xx:成功--表示请求已被成功接收、理解、接受。
3xx:重定向--要完成请求必须进行更进一步的操做。
4xx:客户端错误--请求有语法错误或请求没法实现。
5xx:服务器端错误--服务器未能实现合法的请求。
- 响应头部包含响应报文的附加信息,由 名/值 对组成
- 响应主体包含回车符、换行符和响应返回数据,并非全部响应报文都有响应数据
关闭TCP链接
浏览器处理返回的信息(html、json等)
浏览器处理json
TCP拓展
拿到域名对应的IP地址以后,User-Agent(通常是指浏览器)会以一个随机端口(1024 < 端口 < 65535)向服务器的WEB程序(经常使用的有httpd,nginx等)80端口发起TCP的链接请求。这个链接请求(原始的http请求通过TCP/IP4层模型的层层封包)到达服务器端后(这中间经过各类路由设备,局域网内除外),进入到网卡,而后是进入到内核的TCP/IP协议栈(用于识别该链接请求,解封包,一层一层的剥开),还有可能要通过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序后端
TCP报文格式
TCP/IP协议的详细信息参看《TCP/IP协议详解》三卷本。
下面是TCP报文格式图:浏览器
上图中有几个字段须要重点介绍下:
(1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义以下:
- URG:紧急指针(urgent pointer)有效。
- ACK:确认序号有效。
- PSH:接收方应该尽快将这个报文交给应用层。
- RST:重置链接。
- SYN:发起一个新链接。
- FIN:释放一个链接。
seq:首次是随机产生 后面是等于返回的ack
ack:指望收到对方下一个报文段的第一个数据字节序号服务器
TCP三次握手
假如服务器B和客户机A通信. 当A要和B通讯时
- A首先向B发一个SYN (Synchronize) 标记的包,告诉B请求创建链接. 注意: 一个 SYN包就是仅SYN标记设为1的TCP包. 只有当B受到A发来的SYN包,才可创建链接,除此以外别无他法。
- 接着,B收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操做. 注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.
- A收到SYN/ACK 包,A发一个确认包(ACK),通知B链接已创建。至此,三次握手完成,一个TCP链接完成 注意: ACK包就是仅ACK 标记设为1的TCP包.
序号 |
方向 |
seq |
ack |
SYN |
ACK |
1 |
A->B |
10000 |
0 |
1 |
0 |
2 |
B->A |
20000 |
10000+1=10001 |
1 |
1 |
3 |
A->B |
10001 |
20000+1=20001 |
0 |
1 |
第一次握手:A向B发起链接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0
第二次握手:B收到A的链接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ack是A的seq加1,即10000+1=10001
第三次握手:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001mvc
数据传输过程当中seq和ack的值:
序号 |
方向 |
seq |
ack |
size |
23 |
A->B |
40000 |
70000 |
1514 |
24 |
B->A |
70000 |
40000+1514-54=41460 |
54 |
25 |
A->B |
41460 |
70000+54-54=70000 |
1514 |
26 |
B->A |
70000 |
41460+1514-54=42920 |
54 |
这个54能够先不考虑 当作不存在便可 有兴趣本身查查3d
TCP四次挥手
假如服务器B和客户机A通信. 当A要和B通讯时
- 客户端A没有要发送给服务端B的数据了,想要关闭连接,则发送一个FIN=1,ACK=1的包,告诉B能够关闭链接了,我没有什么数据要给你了。
- 而后B会发送ACK=1的包给A,告诉A我知道你没有什么想给个人了,可是我还有数据要给你,你先等下,我先不想FINISH呢。
- 等B把数据都发送给A以后,B会再次发送一个包,此次FIN=1,表示我这边也想关闭了,咱俩一块儿关把 。
在2和3之间,可能还会有不少B->A的传递,ack均为80001
- 而后A回应一个ACK,表示我知道了,一块儿关吧。B收到这个ACK后,就会CLOSE 可是实际上A不会直接CLOSE,还会进入一个等待时间状态TIME_WAIT
四次挥手过程当中seq和ack的值:
TCP链接的结束是四次挥手的过程,ACK一直等于1
序号 |
方向 |
seq |
ack |
FIN |
ACK |
1 |
A->B |
80000 |
90000 |
1 |
1 |
2 |
B->A |
90000 |
80000+1=80001 |
0 |
1 |
3 |
B->A |
95000 |
80001 |
1 |
1 |
4 |
A->B |
80001 |
95000+1=95001 |
0 |
1 |
参考
github.com/kaola-fed/b…