zoukankan      html  css  js  c++  java
  • HTTP协议探究(序章)

    1 HTTP协议基于TCP协议

    (1)TCP三次握手连接

    • HTTP客户端(Chrome浏览器):
      • IP:192.168.1.47
      • 端口:59875
      • MSS:1460
    • HTTP服务器(Nginx服务器):
      • IP:45.76.37.162
      • 端口:80
      • MSS:1452
    1 	8.893857	192.168.1.47	45.76.37.162	TCP	66	59875 → 80 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
    2 	9.151584	45.76.37.162	192.168.1.47	TCP	66	80 → 59875 [SYN, ACK] Seq=0 Ack=1 Win=29200 Len=0 MSS=1452 SACK_PERM=1 WS=128
    3 	9.151807	192.168.1.47	45.76.37.162	TCP	54	59875 → 80 [ACK] Seq=1 Ack=1 Win=66560 Len=0
    

    (2)第一个HTTP请求

    4 	9.152317	192.168.1.47	45.76.37.162	HTTP 461	GET / HTTP/1.1 
    
    # 具体报文
    Hypertext Transfer Protocol
    	GET / HTTP/1.1
    
    	Host: 45.76.37.162
    
    	Connection: keep-alive
    
    	Cache-Control: max-age=0
    
    	Upgrade-Insecure-Requests: 1
    
    	User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
    
    	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    
    	Accept-Encoding: gzip, deflate
    
    	Accept-Language: zh-CN,zh;q=0.9
    
    	
    
    

    (3)第一个HTTP响应(HTML)

    # ACK报文告知客户端我已收到请求,你可以准备接收我的数据了。
    5	9.409851	45.76.37.162	192.168.1.47	TCP	60	80 → 59875 [ACK] Seq=1 Ack=408 Win=30336 Len=0
    6	9.410305	45.76.37.162	192.168.1.47	TCP	1506	80 → 59875 [ACK] Seq=1 Ack=408 Win=30336 Len=1452 [TCP segment of a reassembled PDU]
    7	9.410551	45.76.37.162	192.168.1.47	TCP	1506	80 → 59875 [ACK] Seq=1453 Ack=408 Win=30336 Len=1452 [TCP segment of a reassembled PDU]
    8	9.410552	45.76.37.162	192.168.1.47	HTTP	1089	HTTP/1.1 200 OK  (text/html)
    9	9.410580	192.168.1.47	45.76.37.162	TCP	54	59875 → 80 [ACK] Seq=408 Ack=3940 Win=66560 Len=0 # 客户端返回收到确认
    
    # 服务器返回的最后一个报文的部分HTTP报文(省略实体内容)
    Hypertext Transfer Protocol
    	HTTP/1.1 200 OK
    
    	Server: nginx/1.12.2
    
    	Date: Wed, 21 Nov 2018 06:57:21 GMT
    
    	Content-Type: text/html
    
    	Content-Length: 3700
     # HTTP报文长为3700
    	Last-Modified: Tue, 06 Mar 2018 09:26:21 GMT
    
    	Connection: keep-alive
    
    	ETag: "5a9e5ebd-e74"
    
    	Accept-Ranges: bytes
    
    	
    
    	[HTTP response 1/2]
    	[Time since request: 0.258235000 seconds]
    	[Request in frame: 103]
    	[Next request in frame: 114] # 这里证明了一次TCP请求可以发送多次HTTP报文
    	[Next response in frame: 120]
    	File Data: 3700 bytes
    
    • HTTP报文太长了,一个TCP段无法发送完,于是分成了n份,n为多少呢?
      • HTTP报文长为3700,TCP MSS为1452,3700为HTTP实体大小 + HTTP首部(239)才是HTTP包的总大小 = 3939,3939 / 1452 = 3次。
    • TCP客户端怎么知道TCP服务端,分段发送已经完成?
      • 客户端HTTP请求时,发送PSH,ACK报文
      • 服务器先返回ACK报文,告知收到
      • 接着正式发送分段的HTTP报文(每次都是ACK)
      • 最后一段HTTP报文为PSH,ACK报文
    • 为什么HTTP请求时,发送的是PSH,ACK报文?
      • 因为只放ACK报文,服务器无法确认客户端是否发送完毕了。
      • 简而言之,PSH报文能够告知对方,我已发送完毕,请处理。

    (4)第二个请求

    10	9.419095	192.168.1.47	45.76.37.162	HTTP	404	GET /nginx-logo.png HTTP/1.1 
    
    # 具体报文
    Hypertext Transfer Protocol
    	GET /nginx-logo.png HTTP/1.1
    
    	Host: 45.76.37.162
    
    	Connection: keep-alive
    
    	User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
    
    	Accept: image/webp,image/apng,image/*,*/*;q=0.8
    
    	Referer: http://45.76.37.162/
    
    	Accept-Encoding: gzip, deflate
    
    	Accept-Language: zh-CN,zh;q=0.9
    
    	
    
    

    (5)第二个响应(图片)

    11	9.679782	45.76.37.162	192.168.1.47	HTTP	660	HTTP/1.1 200 OK  (PNG)
    
    # 具体报文(省略实体报文)
    Hypertext Transfer Protocol
    	HTTP/1.1 200 OK
    
    	Server: nginx/1.12.2
    
    	Date: Wed, 21 Nov 2018 06:57:21 GMT
    
    	Content-Type: image/png
    
    	Content-Length: 368
    
    	Last-Modified: Tue, 06 Mar 2018 09:26:21 GMT
    
    	Connection: keep-alive
    
    	ETag: "5a9e5ebd-170"
    
    	Accept-Ranges: bytes
    
    	
    
    	[HTTP response 2/2]
    	[Time since request: 0.260687000 seconds]
    	File Data: 368 bytes
    
    • Content-Length = 368,但是TCP payload 为606,606 < 1452,一次发送完毕。HTTP首部为238字节。

    (6)省略TCP的4次挥手断开连接

    2 总结

    • HTTP协议基于TCP协议
    • HTTP报文过长需要TCP分段传输
    • 每次HTTP请求或响应都需要设置PSH标志为1,用于标志HTTP请求或响应完成
    • TCP的MSS由双方共同决定,选择最小的值(如:1452 < 1460,所以为MSS),短板效应(防止处理速度快的一方压垮慢的一方)
    • HTTP首部很长,上述两次首部一次为239字节,一次为238字节(HTTP2.0有改善,未来研究一下)。
    • HTTP1.1协议可以在一次TCP连接中,发送多次HTTP报文(HTTP1.0就不可以)
  • 相关阅读:
    java中volatile关键字的含义
    2019年个人总结
    跟随Javac代码来解答字节码的疑惑
    Python装饰器实现带参数和不带参数
    try with resource当中你没有注意到点。。
    IDEA中,已经被加到版本库的文件如何在提交的时候忽略它们
    连接mysql客户端报错: java.sql.SQLException: Unable to load authentication plugin 'caching_sha2_password'
    从字节码层次看i++和++i
    对lambda表达式的字节码实现个人理解
    解决mvn clean install的报错The packaging for this project did not assign a file to the build artifact
  • 原文地址:https://www.cnblogs.com/linzhanfly/p/9996119.html
Copyright © 2011-2022 走看看