协议模型、HTTP(TCP)请求的具体过程、TCP三次握手、TCP四次挥手

回答http协议报文的时候要有条理性

  1. 首先是tcp通过ip+端口port连接以后传http
  2. http协议-请求报文:请求行, 请求头, 空行, 请求体
  3. http协议-响应报文:返回行, 返回头,空行, 响应体
  4. http协议-请求方法:get/post==>有无请求体, 容量大小

7层协议模型

TCP/IP:
数据链路层:ARP,RARP
网络层: IP,ICMP,IGMP
传输层:TCP ,UDP,UGP
应用层:HTTP,Telnet,FTP,SMTP,SNMP.

OSI:
物理层:EIA/TIA-232, EIA/TIA-499, V.35, V.24, RJ45, Ethernet, 802.3, 802.5, FDDI, NRZI, NRZ, B8ZS
数据链路层:Frame Relay, HDLC, PPP, IEEE 802.3/802.2, FDDI, ATM, IEEE 802.5/802.2
网络层:IP,IPX,AppleTalk DDP
传输层:TCP,UDP,SPX
会话层:RPC,SQL,NFS,NetBIOS,names,AppleTalk,ASP,DECnet,SCP
表示层: TIFF,GIF,JPEG,PICT,ASCII,EBCDIC,encryption,MPEG,MIDI,HTML
应用层:HTTP,FTP,WWW,Telnet,NFS,SMTP,Gateway,SNMP

物理链路, 网络传输, 会话表示应用

DNS解析

将域名解释为ip地址
DNS域名解析采用的是递归查询的方:
先去找DNS缓存->hosts->找根域名服务器->根域名又会去找下一级
DNS优化两个方面:DNS缓存、DNS负载均衡

通过ip + port构建socket连接

  1. DNS解析过程, 如把www.qq.com变成一个ip,如果url不包含端口号,则会使用该协议的默认端口号,HTTP协议的默认端口号为80。

  2. 建立TCP连接(三次握手):
    在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接,该连接是通过TCP来完成的,
    该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。
    HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能,才能进行更层协议的连接,
    因此,首先要建立TCP-socket连接,socket是通过ip和port建立的, 一般TCP连接的端口号是80。

  3. 请求过程:
    连接成功后,开始像web服务器发送请求,这个请求一般是GET或POST请求。
    Web浏览器向Web服务器发送请求命令:
    一旦建立了TCP连接,Web浏览器就会向Web服务器发送请求命令。例如:GET/sample/hello.jsp HTTP/1.1。
    Web浏览器发送请求头信息:
    浏览器发送其请求命令之后,还要以头信息的形式向Web服务器发送一些别的信息,之后浏览器发送了一空白行来通知服务器,它已经结束了该头信息的发送。
    Web服务器应答:
    客户机向服务器发出请求后,服务器会客户机回送应答, HTTP/1.1 200 OK ,应答的第一部分是协议的版本号和应答状态码。
    Web服务器发送应答头信息:
    正如客户端会随同请求发送关于自身的信息一样,服务器也会随同应答向用户发送关于它自己的数据及被请求的文档。
    Web服务器向浏览器发送数据:
    Web服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此为结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据。

  4. 关闭TCP连接(四次挥手):当应答结束后,web浏览器与web服务器必须断开,以保证其它web浏览器能够与web服务器建立连接。

常用的HTTP方法

GET: 完整请求一个资源 (常用)
HEAD: 仅请求响应首部
POST:提交表单 (常用)
PUT: (webdav) 上传文件(但是浏览器不支持该方法)
DELETE:(webdav) 删除
OPTIONS:返回请求的资源所支持的方法的方法
TRACE: 追求一个资源请求中间所经过的代理(该方法不能由浏览器发出)

建立连接后的请求

HTTP请求报文由三部分组成:请求行,请求头、空格、请求正文

请求行:用于描述客户端的请求方式(GET/POST等),请求的资源名称(URL)以及使用的HTTP协议的版本号
例子: GET /versions?version=1.2.0&channel=App Store HTTP/1.1

请求头:用于描述客户端请求哪台主机及其端口,以及客户端的一些环境信息等
Referer, Cookie, User-Agent, token, Accept-Charset

空行:空行就是\r\n (POST请求时候有,GET無)

请求正文:当使用POST等方法时,通常需要客户端向服务器传递数据。
这些数据就储存在请求正文中(GET方式是保存在url地址后面,不会放到这里)

POST和GET的区别就是因为有了请求体中间多了一行空行, 以及url不一样

具体例子:
POST  /index.php HTTP/1.1    请求行

Host: localhost

User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2  请求头

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8

Accept-Language: zh-cn,zh;q=0.5

Accept-Encoding: gzip, deflate

Connection: keep-alive

Referer: http://localhost/

Content-Length:25

Content-Type:application/x-www-form-urlencoded

  空行

username=aa&password=1234  请求数据

建立连接后的响应

HTTP响应也由三部分组成:状态行,响应头,空行,消息体

状态行包括:协议版本、状态码、状态码描述
例子: HTTP/1.1 200 OK

响应头:响应头用于描述服务器的基本信息,以及客户端如何处理数据
Set-Cookie, Content-Type,

空行:CRLF(即 \r\n)分割

消息体:数据

具体例子:

HTTP/1.1 200 OK  状态行

Date: Sun, 17 Mar 2013 08:12:54 GMT  响应头部

Server: Apache/2.2.8 (Win32) PHP/5.2.5

X-Powered-By: PHP/5.2.5

Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/

Expires: Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

Pragma: no-cache

Content-Length: 4393

Keep-Alive: timeout=5, max=100

Connection: Keep-Alive

Content-Type: text/html; charset=utf-8

空行

html、json等的具体内容

Connection:keep-alive

TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。
保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

TCP三次握手

如果TCP连接保持,第二个请求发送就没有这“三次握手”的消耗。HTTP/2中同一个TCP连接里还可以并发地传输http请求。
因此连接以后, 保持连接就可以减少每次三次握手的消耗。

不要将确认序号Ack与标志位中的ACK搞混了。确认方Ack=发起方Seq+1,两端配对。
理解三次握手的核心从标志位, 序列号, 确认号来理解。

其中比较重要的字段有:

(1)序号(sequence number):Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

(2)确认号(acknowledgement number):Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。

(3)标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效。 Aacknowledgement Number, 确认号。
PSH:接收方应该尽快将这个报文交给应用层。
RST:重置连接。
SYN:发起一个新连接。 Synchronize Sequence Numbers, 同步序列编号。
FIN:释放一个连接。

第一次握手: 客户端给服务端发送报文,标志位为SYN(表示请求建立新连接), 序号为Seq=x(x一般为1), 随后客户端进入SYN-SENT阶段。
第二次握手: 服务端给客户端回复报文,标志位为SYN和ACK(表示接收和发送), 序号为Seq=y, 确认号为Ack=x+1
第三次握手: 客户端收到以后回复服务端,标志位为ACK(表示接收), 序号为Seq=x+1, 确认号为Ack=y+1

第一次握手: 客户端给服务端发送报文,SYN, Seq=x, 发送。
第二次握手: 服务端给客户端回复报文,SYN和ACK,Seq=y, Ack=x+1, 接收发送。
第三次握手: 客户端收到以后回复服务端,ACK, Seq=x+1, Ack=y+1, 接收。

我使用wireshark来进行捕获的结果是:

TCP四次挥手

第一次挥手: 客户端想要释放连接发送报文, 标志位FIN, 序号Seq=x, 进入半关闭状态,停止发送数据,但是可以接收数据, 发出。
第二次挥手: 服务端收到请求确认客户端想要释放连接, 标志位ACK, 序号Seq=y, Ack=x+1, 半关闭状态, 准备释放连接, 发出报文
第三次挥手: 服务端确认发出报文以后,标志位FIN,ACK, Seq=z, Ack=x+1, 停止向客户端发送数据
第四次挥手: 客户端接收服务端发出的信号, 标志位ACK, Seq=x+1, Ack=z+1, 结束

第一次挥手: 客户端想要释放连接, FIN, Seq=x, 发出。
第二次挥手: 服务端确认客想要释放连接, ACK, Seq=y, Ack=x+1, 第一阶段表示收到, 准备数据处理完以后释放。
第三次挥手: 服务端确认发出报文以后, FIN,ACK, Seq=z, Ack=x+1, 第二阶段表示处理完毕, 正式释放。
第四次挥手: 客户端接收结束信号, ACK, Seq=x+1, Ack=z+1, 结束。

为什么“握手”是三次,“挥手”却要四次?

如果请求是前两次连接: 服务端发出去就以为连接成功,然后不断发送数据,但是客户端没有收到报文认为连接没有成功,忽略接收数据。
挥手四次,服务器端会先返回一个响应报文,代表接收到了客户端发出的FIN请求,而后在数据传输完了之后,再发出FIN请求,表示服务器端已经准备好断开连接了。

TCP建立连接时之所以只需要"三次握手",是因为在第二次"握手"过程中,服务器端发送给客户端的TCP报文是以SYN与ACK作为标志位的。
SYN是请求连接标志,表示服务器端同意建立连接;ACK是确认报文,表示告诉客户端,服务器端收到了它的请求报文。

SYN建立连接报文与ACK确认接收报文是在同一次"握手"当中传输的,所以"三次握手"不多也不少,正好让双方明确彼此信息互通。
TCP释放连接时之所以需要“四次挥手”,是因为ACK确认接收报文和FIN释放连接报文是分别由第二次和第三次"握手"传输的。

为何建立连接时一起传输,释放连接时却要分开传输?
建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。
释放连接时,被动方服务器,突然收到主动方客户端释放连接的请求时并不能立即释放连接,因为还有必要的数据需要处理,
所以服务器先返回ACK确认收到报文,经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。

为什么客户端在TIME-WAIT阶段要等2MSL(Maximum Segment Lifetime最大段生存周期)?

为的是确认服务器端是否收到客户端发出的ACK确认报文

当客户端发出最后的ACK确认报文时,并不能确定服务器端能够收到该段报文。
所以客户端在发送完ACK确认报文之后,会设置一个时长为2MSL的计时器。
MSL指的是Maximum Segment Lifetime:一段TCP报文在传输过程中的最大生命周期。
2MSL即是服务器端发出为FIN报文和客户端发出的ACK确认报文所能保持有效的最大时长。

服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN报文;
如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。
客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;
否则客户端在2MSL内没有再次收到来自服务器端的FIN报文,说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。
客户端要经历时长为2SML的TIME-WAIT阶段;这也是为什么客户端比服务器端晚进入CLOSED阶段的原因.

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。
服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,
若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。
若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

posted @ 2020-06-17 15:53  Adamanter  阅读(480)  评论(0)    收藏  举报