HTTP协议探究(序章)
2024-09-05 05:16:19
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\r\n
Host: 45.76.37.162\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
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\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n
(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\r\n
Server: nginx/1.12.2\r\n
Date: Wed, 21 Nov 2018 06:57:21 GMT\r\n
Content-Type: text/html\r\n
Content-Length: 3700\r\n # HTTP报文长为3700
Last-Modified: Tue, 06 Mar 2018 09:26:21 GMT\r\n
Connection: keep-alive\r\n
ETag: "5a9e5ebd-e74"\r\n
Accept-Ranges: bytes\r\n
\r\n
[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\r\n
Host: 45.76.37.162\r\n
Connection: keep-alive\r\n
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\r\n
Accept: image/webp,image/apng,image/*,*/*;q=0.8\r\n
Referer: http://45.76.37.162/\r\n
Accept-Encoding: gzip, deflate\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n
(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\r\n
Server: nginx/1.12.2\r\n
Date: Wed, 21 Nov 2018 06:57:21 GMT\r\n
Content-Type: image/png\r\n
Content-Length: 368\r\n
Last-Modified: Tue, 06 Mar 2018 09:26:21 GMT\r\n
Connection: keep-alive\r\n
ETag: "5a9e5ebd-170"\r\n
Accept-Ranges: bytes\r\n
\r\n
[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就不可以)
最新文章
- 利用Generator解决异步回调原理
- 在基于vue的webpack脚手架开发中使用了代理转发,结果浏览器发出的请求中不带cookie导致登录时总是session失效怎么办?
- 解决警告“ld: warning: directory not found for option
- <;实训|第十一天>;学习一下linux中的进程,文件查找,文件压缩与IO重定向
- 在 .NET 4.5 中反射机制的变更
- NGUI3.5系列教程之 UILabel
- poj2242
- 各种Adapter的用法
- xml的生成和发送
- SQL注入漏洞产生的原因是什么?怎么防止?XSS呢?
- 关于《common-net》的ftp上传
- 利用反射C#获取事件列表
- 关于ASP.NET MVC中Form Authentication与Windows Authentication的简单理解
- shell基础 -- 基本正则表达式
- Handling Errors and Exceptions
- 转:修改Android签名证书keystore的密码、别名alias以及别名密码
- Effective C++ .33 子类的名称覆盖
- Java实战及解析 — Maven快速入门
- vuejs on
- LA 5902 - Movie collection 树状数组(Fenwick树)
热门文章
- Java 类加载
- vue问题五:element ui组件的开始时间-结束时间验证
- v-if与v-show的区别?
- SQL-W3School-高级:SQL VIEW(视图)
- kotlin使用中辍标记法调用函数
- python-30个骚操作
- java网络通信:异步非阻塞I/O (NIO)
- 消息队列之ActiveMQ学习笔记(一、下载及安装)
- jquery中的$(document).ready(function(){})和$(window).load()比较
- 为什么linux系统中init被systemd替换了