详解http协议

什么是HTTP协议

定义

Http协议即超文本传送协议 (HTTP-Hypertext transfer protocol) 。

它定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。从层次的角度看,HTTP是面向(transaction-oriented)应用层协议,它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。并且详细地规定了客户端浏览器与服务器之间互相通信的规则。

http主要方法

http状态码

收到请求消息之后, Web 服务器会对其中的内容进行解析, 通过 URI和方法来判断“对什么”“进行怎样的操作”, 并根据这些要求来完成自己的工作, 然后将结果存放在响应消息中。 在响应消息的开头有一个状态码,它用来表示操作的执行结果是成功还是发生了错误。

HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型。

响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)

HTTP状态码列表:

版本变迁

1991年,HTTP/0.9:支持GET请求方式获取文本数据(比如HTML),且不支持请求头,响应头,无法向服务器传递太多信息。

1996年,HTTP/1.0:支持POST、HEAD等请求方法,支持请求头、响应头等,支持更多种数据类型(不再局限于文本数据)浏览器的每次请求都需要与服务器建立一个TCP连接,请求处理完成后立即断开TCP连接。比如当前HTML在被浏览器解析时,发现有一个图片资源,就是再次建立TCP连接,然后关闭TCP连接。

1997年,HTTP/1.1:

  • 支持PUT,DELETE请求,采用持久连接,多个HTTP请求,可以共用一个TCP连接。

  • 这版协议使用最广泛。

2015,HTTP/2.0

2018,HTTP/3.0

HTTP报文格式

请求报文

HTTP请求报文第一行是请求行,其后继的行叫做首部行。每行由一个回车和换行符结束,最后一行再附加一个回车换行符。一个请求报文至少为一行。

  • 请求行:由请求方法、URL(包含参数)和协议版本组成

  • 请求头部:由多个key-value值组成

  • 空行:请求报文使用空行将请求头部和请求数据分隔

  • 请求数据:GET方法没有携带数据,POST方法会携带一个body

例:

响应报文

  • 状态行:由协议版本、状态码和状态值组成

  • 响应头:由多个key-value值组成

  • 空行:响应报文使用空行将响应头和响应体分隔

  • 响应体:响应数据,在上面是一段HTML

例:

HTTP传输原理

概述

以在浏览器中输入www.baidu.com为例:

  1. 对www.baidu.com这个网址进行DNS域名解析,得到对应的IP地址

  2. 根据这个IP,找到对应的服务器,发起TCP的三次握手

  3. 建立TCP连接后发起HTTP请求

  4. 服务器响应HTTP请求,浏览器得到html代码

  5. 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等)(先得到html代码,才能去找这些资源)

  6. 浏览器对页面进行渲染呈现给用户

  7. 服务器关闭关闭TCP连接

详细步骤
  1. DNS解析

a)首先会搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存)

b)如果浏览器自身的缓存里面没有找到,那么浏览器会搜索系统自身的DNS缓存

c)如果还没有找到,那么尝试从 hosts文件里面去找

d)在前面三个过程都没获取到的情况下,就递归地去域名服务器去查找

  1. TCP连接建立(三次握手)

拿到域名对应的IP地址之后,User-Agent(一般指浏览器)会以一个随机端口(1024<端口<65535)向服务器的WEB程序(常用的有httpd,nginx)等的80端口。这个连接请求(原始的http请求经过TCP/IP4层模型的层层封包)到达服务器端后(这中间有各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别连接请求,解封包,一层一层地剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终达到WEB程序,最终建立了TCP/IP的连接

  1. 发起HTTP请求(建立连接后)

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

  1. 服务器响应http请求,浏览器得到html代码

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

状态行包括:协议版本、状态码、状态码描述

  1. 浏览器解析html代码,并请求html代码中的资源

浏览器拿到html文件后,就开始解析其中的html代码,遇到js/css/image等静态资源时,就向服务器端去请求下载(会使用多线程下载,每个浏览器的线程数不一样),这个时候就用上keep-alive特性了,建立一次HTTP连接,可以请求多个资源,下载资源的顺序就是按照代码里面的顺序,但是由于每个资源大小不一样,而浏览器又是多线程请求资源,所以这里显示的顺序并不一定是代码里面的顺序。

  1. 浏览器对页面进行渲染呈现给用户

最后,浏览器利用自己内部的工作机制,把请求的静态资源和html代码进行渲染,渲染之后呈现给用户,浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念:reflow(回流)和repain(重绘)。

DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少地减少reflow和repain。JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,JS有可能修改DOM结构,意味着JS执行完成前,后续所有资源的下载是没有必要的,所以JS是单线程,会阻塞后续资源下载。

  1. 服务器关闭关闭TCP连接

一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:

Connection:keep-alive 

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

什么是http2

http2:

  • 二进制格式:1.x是文本协议,然而2.0是以二进制帧为基本单位,可以说是一个二进制协议,将所有传输的信息分割为消息和帧,并采用二进制格式的编码,一帧中包含数据和标识符,使得网络传输变得高效而灵活;

  • 多路复用:2.0版本的多路复用多个请求共用一个连接,多个请求可以同时在一个TCP连接上并发,主要借助于二进制帧中的标识进行区分实现链路的复用;

  • 头部压缩:2.0版本使用HPACK算法对头部header数据进行压缩,从而减少请求的大小提高效率,这个非常好理解,之前每次发送都要带相同的header,显得很冗余,2.0版本对头部信息进行增量更新有效减少了头部数据的传输;

  • 服务端推送:在2.0版本允许服务器主动向客户端发送资源,这样在客户端可以起到加速的作用;

http2的重要改动:
  • 降低延迟(多路复用):使用多路复用来降低高延迟的问题,多路复用指的是使用Stream让多个请求可以共享一个TCP连接,解决HOL Blocking(head of line blocking)的问题,同时提升带宽利用率。

    • HTTP1.1中keep-alive用的是http pipelining本质上也是multiplexing,但是具体实现方案不理想 

    • 主流浏览器都默认禁止pipelining,也是因为HOL阻塞问题导致。

  • 服务端推送:HTTP1.X的推送都是半双工,所以在2.0是实现真正的服务端发起请求的全双工,另外在WebSocket在这一块大放异彩

  • 请求优先级:针对引入多路复用的一个兜底方案,多路复用使用多个Stream的时候容易单请求阻塞问题,也就是前文所说的和管道连接一样的问题,SPDY通过设置优先级的方式让重要请求优先处理,比如页面的内容应该先进行展示,之后再加载CSS文件美化以及加载脚本互动等等,实际减少用户不会在等待过程中关闭页面的几率

  • Header压缩:HTTP1.X的header很多时候都是多余的,所以2.0 会自动选择合适的压缩算法自动压缩请求加快请求和响应速度。

什么是http3

这个版本是划时代的改变,在HTTP3.0中,将弃用TCP协议,改为使用基于UDP协议的QUIC协议实现。需要注意QUIC是谷歌提出的(和2.0 的SPDY 一样),QUIC指的是快速 UDP Internet 连接,既然使用了UDP,那么也意味着网络可能存在丢包和稳定性下降,谷歌当然不会让这样的事情发生,所以他们提出的QUIC既可以保证稳定性,又可以保证SSL的兼容,因为HTTP3上来就会和TLS1.3一起上线。

基于这些原因,制定网络协议IETF的人马上基本都同意了QUIC的提案(太好了又能白嫖成果),于是HTTP3.0 就这样来了。但是这只是最基本的草案,后续的讨论中希望QUIC可以兼容其他的传输协议,最终的排序如下IP / UDP / QUIC / HTTP。另外TLS有一个细节优化是在进行连接的时候浏览器第一次就把自己的密钥交换的素材发给服务器,这样进一步缩短了交换的时间。

为什么要使用http3

为什么HTTP3.0要从协议根本上动刀,那是因为HTTP/2虽然解决了HTTP协议无法多路复用的问题,但是没有从TCP层面解决问题,具体的TCP问题体现如下:

  • RTT:RTT是Round Trip Time的缩写,简单来说就是通信一来一回的时间。

  • 队头阻塞,HTTP/2 多个请求跑在一个 TCP 连接中,如果此时序号较低的网络请求被阻塞,那么即使序列号较高的 TCP 段已经被接收了,应用层也无法从内核中读取到这部分数据,从 HTTP 视角看就是多个请求被阻塞了,并且页面也只是加载了一部分内容;

  • TCP 和 TLS 握手时延缩短:TCL 三次握手和 TLS 四次握手,共有 3-RTT 的时延,HTPT/3最终压缩到1 RTT(难以想象有多快);

  • 连接迁移需要重新连接,移动设备从 4G 网络环境切换到 WIFI 时,由于 TCP 是基于四元组来确认一条 TCP 连接的,那么网络环境变化后,就会导致 IP 地址或端口变化,于是 TCP 只能断开连接,然后再重新建立连接,切换网络环境的成本高

所以后续谷歌的研究方向转为研究QUIC,实际上就是改良UDP协议来解决TCP协议自身存在的问题

为什么http3选择UDP协议

这就引出另一个问题,为什么3.0有很多协议可以选择为什么使用UDP,通常有下面的几个点:

  • 基于TCP 协议的设备很多,兼容十分困难

  • TCP是Linux内部的重要组成,修改非常麻烦,或者说压根不敢动

  • UDP本身无连接的,没有建立连接和断连的成本

  • UDP数据包本身就不保证稳定传输所以不存在阻塞问题(属于爱要不要)

  • UDP改造相对其他协议改造成本低很多 

HTTP协议真的是无状态的么?

仔细阅读HTTP1.x和HTTP/2以及HTTP3.0三个版本的对比,其实会发现HTTP无状态的定义偷偷发生了变化的,为什么这么说?

我们需要弄清一个概念,那就是Cookie和Session虽然让HTTP实现了“有状态”,但是其实这和HTTP协议本身的概念是没有关系的。

Cookie和Session的出现根本目的是保证会话状态本身的可见性,两者通过创立多种独立的状态“模拟”用户上一次的访问状态,但是每一次的HTTP请求本身并不会依赖上一次HTTP的请求,单纯从广义的角度看待其实所有的服务都是有状态的,但是这并不会干扰HTTP1.X本身无状态的定义。

此外HTTP协议所谓的无状态指的是每个请求是完全独立的,在1.0备忘录定义中也可以看出一次HTTP连接其实就是一次TCP连接,到了HTTP1.1实现了一个TCP多个HTTP连接依然是可以看作独立的HTTP请求。

说了这么多,其实就是说HTTP1.X在不靠Cookie和Session扶着的时候看做无状态是对的,就好比游戏里面的角色本身的数值和武器附加值的对比,武器虽然可以让角色获得某种状态,但是这种状态并不是角色本身特有的,而是靠外力借来的。

然而随着互联网发展,到了HTTP/2和HTTP3之中HTTP本身拥有了“状态”定义,比如2.0关于HEADER压缩产生的HPACK算法(需要维护静态表和动态表),3.0还对HPACK算法再次升级为QPACK让传输更加高效。

所以总结就是严谨地来说HTTP1.X是无状态的,在Cookie和Session的辅助下实现了会话访问状态的保留。到了HTTP/2之后HTTP是有状态的, 因为在通信协议中出现了一些状态表来维护双方重复传递的Header字段减少数据传输。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/643845.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

缩进在编程中的重要性及正确使用方法

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 前言 缩进不当引发的问题 缩进的正确使用方法 缩进错误的调试与修复 总结 前言 在编程世…

微信小程序连接阿里云快速入门【物联网】

一、前言 1.1 项目背景 随着5G的逐渐普及&#xff0c;万物互联的浪潮已经席卷而来。在万物互联的场景下&#xff0c;如何实现设备之间的互联互通&#xff0c;成为了一个亟待解决的问题。 微信小程序作为一款轻量级的小程序开发框架&#xff0c;以其简洁的语法和丰富的组件库…

【ZYNQ】AXI-Quad-SPI SDK 开发记录 测试

前人工作 如前人工作&#xff0c;在Navigate to BSP Settings中找到历例程 file:///F:/Xilinx/Vitis/2019.2/data/embeddedsw/XilinxProcessorIPLib/drivers/spi_v4_5/doc/html/api/example.html使用XSpi_LowLevelExample例子&#xff0c;源代码的AI解析 int XSpi_LowLeve…

Java虚拟机揭秘-底层驱动力,性能保障!

Java虚拟机作为Java技术体系的核心组成部分&#xff0c;其重要性不言而喻。它不仅为Java提供了跨平台的能力&#xff0c;更是Java程序运行的基石。本文将为您深入解析Java虚拟机的工作原理、作用和应用场景&#xff0c;并通过生动的实例让您彻底理解这一关键技术。 一、Java虚拟…

温故而知新-MySQL篇【面试复习】

温故而知新-数据库篇【面试复习】 前言版权推荐温故而知新-Mysql篇Mysql常见面试题Mysql事务Mysql索引Mysql锁Mysql日志Mysql中的Buffer 数据库的三范式是什么MySQL对于LRU的优化InnoDB三大特性自适应哈希索引&#xff08;Adaptive Hash Index&#xff09;插入缓存&#xff08;…

驱动与系统学习网址

DRM&#xff08;Direct Rendering Manager&#xff09;学习简介-CSDN博客 Android Qcom Display学习(零)-CSDN博客 https://blog.csdn.net/hexiaolong2009/category_9705063.htmlhttps://blog.csdn.net/hexiaolong2009/category_9705063.htmlRender Hell —— 史上最通俗易懂…

【ECharts】数据可视化

目录 ECharts介绍ECharts 特点Vue2使用EChats步骤安装 ECharts引入 ECharts创建图表容器初始化图表更新图表 示例基本柱状图后台代码vue2代码配置 组件代码运行效果 基本折线图示例代码组件 基础饼图示例代码后台前端配置组件运行效果 其他 ECharts介绍 ECharts 是一个由百度开…

DataGear 制作服务端分页的数据可视化看板

DataGear 2.3.0 版本新增了附件图表数据集特性&#xff08;在新建图表时将关联的数据集设置为 附件 &#xff0c;具体参考官网文档定义图表章节&#xff09;&#xff0c;在制作看板时&#xff0c;可以基于此特性&#xff0c;结合dg-chart-listener&#xff0c;利用服务端数据扩…

使用VCPKG编译并使用Qt5

一、背景 Qt就不介绍了。VCPKG可以看这里VCPKG资料记录_vcpkg boost 多久-CSDN博客 为什么搞Qt5而不是Qt6&#xff1f;因为Qt5比较稳定吧。而且我公司也是用的Qt5。 为什么要自己编译而不是去下载Qt5&#xff1f; 第一&#xff0c;因为Qt5在Qt在线安装版本只提供到Qt5.15.2&…

C语言内存函数超详细讲解

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 C语言内存函数超详细讲解 收录于专栏【C语言学习】 本专栏旨在分享学习C语言学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. m…

linux文件权限常用知识点,基于Linux(openEuler、CentOS8)

目录 知识点常用实例 知识点 真实环境文件显示 解读 常用实例 文件所有者 chown -R nginx:nginx /home/source目录权限(R选填必须大写<遍历子文件夹及文件>) chmod -R 755 /home/sourcechmod -R 777 /home/source

【小程序八股文】系列之篇章二 | 小程序的核心机制

【小程序八股文】系列之篇章二 | 小程序的核心机制 前言三、微信小程序原理与运行机制简述一下微信小程序的原理微信小程序的双线程的理解为什么不采用浏览器多线程模式&#xff1f;为什么是双线程&#xff1f;&#xff08;出发点&#xff1a;安全&#xff0c;快速&#xff0c;…

2.Redis之Redis的背景知识

Redis 是一个在内存中存储数据的中间件 用于作为数据库,用于作为数据缓存. 在分布式系统中能够大展拳脚~ 1.Redis的特性介绍(优点) 1.1 在内存中存储数据 MySQL 主要是通过"表"的方式来存储组织数据的,"关系型数据库" Redis 主要是通过“键值对" 的…

safetensors介绍

1 介绍 safetensors 是 Huggingface 推出的一种可靠、易移植的机器学习模型存储格式&#xff0c;用于安全地存储 Tensor&#xff0c;而且速度很快&#xff08;零拷贝&#xff09;。 safetensors 格式结构&#xff1a; 8 bytes&#xff1a;一个无符号的整数&#xff0c;表示…

1106 2019数列

solution 维护长度为4的数组&#xff0c;对于第四位之后的数字&#xff0c;为所维护数组的所有元素之和 的个位数 #include<iostream> using namespace std; int main(){int n, a[4] {2, 0, 1, 9}, cnt 0, d;scanf("%d", &n);for(int i 0; i < n; …

WSL2添加桌面显示

编译 autoscan && aclocal && autoconf && automake --add-missing 自动 #!/bin/shrun () {echo "running: $*"eval $*if test $? ! 0 ; thenecho "error: while running $*"exit 1fi }run aclocal run autoheader run automak…

k8s命令式对象管理和配置

kubectl补全: # dnf install -y bash-completion # echo "source <(kubectl completion bash)" >> ~/.bashrc # kubectl completion bash > /etc/bash_completion.d/kubectl 命令式对象管理 kubectl命令 # 查看所有pod kubectl get pod # 查看某个po…

01-02.Vue的常用指令(二)

01-02.Vue的常用指令&#xff08;二&#xff09; 前言v-model&#xff1a;双向数据绑定v-model举例&#xff1a;实现简易计算器Vue中通过属性绑定为元素设置class 类样式引入方式一&#xff1a;数组写法二&#xff1a;在数组中使用三元表达式写法三&#xff1a;在数组中使用 对…

Python3 笔记:IDLE的几个基本设置

1、设置字体&#xff1a; Options > Configure IDLE > Fonts 2、设置文字颜色&#xff08;设置高亮&#xff09;&#xff1a; Options > Configure IDLE > Highlights 3、设置背景颜色&#xff1a; Options > Configure IDLE > Highlights 4、设置窗口&a…

存储+调优:存储-IP-SAN-EXTENSION

存储调优&#xff1a;存储-IP-SAN-EXTENSION 文件系统的锁标记 GFS&#xff08;锁表空间&#xff09; ----------- ------------ ------------- 节点 | ndoe1 | | node2 | | node3 | ---------- ------…