编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 1.1通过看新闻熟悉网络
  • 1.2通过购物熟悉网络加密
  • 1.3从0到1部署电商网站

1.1通过看新闻熟悉网络

目录介绍

  • 01.在浏览器输入链接
    • 1.1 输入什么链接
    • 1.2 提取链接协议
    • 1.3 域名请求解析
    • 1.4 Mac和IP地址
  • 02.HTTP请求准备
    • 2.1 确定请求方法
    • 2.2 构建请求URL
  • 03.HTTP请求构建
    • 3.1 请求报问规范
    • 3.2 设置请求行
    • 3.3 设置请求头
    • 3.4 设置请求体
  • 04.HTTP请求发送
    • 4.1 建立网络连接
    • 4.2 发送请求头
    • 4.3 发送请求体
    • 4.4 等待服务器响应
  • 05.HTTP返回构建
    • 5.1 构建响应码
    • 5.2 构建响应头
    • 5.3 构建响应体
    • 5.4 发送响应数据

01.在浏览器输入链接

1.1 输入什么链接

1.2 提取链接协议

1.3 域名请求解析

  • HTTP协议,几乎是每个人上网用的第一个协议,同时也是很容易被人忽略的协议。
  • 既然说看新闻,咱们就先登录http://www.163.com。http://www.163.com是个URL,叫作统一资源定位符。
  • 之所以叫统一,是因为它是有格式的。HTTP称为协议,www.163.com是一个域名,表示互联网上的一个位置。有的URL会有更详细的位置标识,例如http://www.163.com/index.html。正是因为这个东西是统一的,所以当你把这样一个字符串输入到浏览器的框里的时候,浏览器才知道如何进行统一处理。

02.HTTP请求准备

  • **浏览器会将www.163.com这个域名发送给DNS服务器,让它解析为IP地址。**有关DNS的过程,其实非常复杂,这里先不管,反正它会被解析成为IP地址。那接下来是发送HTTP请求吗?
  • 不是的,HTTP是基于TCP协议的,当然是要先建立TCP连接了,怎么建立呢?还记得三次握手吗?
  • 目前使用的HTTP协议大部分都是1.1。在1.1的协议里面,默认是开启了Keep-Alive的,这样建立的TCP连接,就可以在多次请求中复用。
  • 学习了TCP之后,你应该知道,TCP的三次握手和四次挥手,还是挺费劲的。如果好不容易建立了连接,然后就做了一点儿事情就结束了,有点儿浪费人力和物力。

2.1 确定请求方法

  • 确定请求方法:根据用户在浏览器中的操作(例如点击链接或提交表单),浏览器确定要使用的HTTP请求方法。
    • 常见的方法包括GET、POST、PUT、DELETE等。

2.2 构建请求URL

  • 构建URL:浏览器将用户输入的URL与当前页面的基本URL进行组合,生成完整的请求URL。
    • 这个URL包含了协议、主机名、路径和查询参数等信息。

03.HTTP请求构建

3.1 请求报问规范

  • 建立了连接以后,浏览器就要发送HTTP的请求,请求的格式就像这样。
    • image
      image
  • HTTP的报文大概分为三大部分。
    • 第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体。

3.2 设置请求行

3.3 设置请求头

3.4 设置请求体

3.1 第一部分:请求行

  • 在请求行中,URL就是http://www.163.com,版本为HTTP 1.1。这里要说一下的,就是方法。方法有几种类型呢?
  • 对于访问网页来讲,最常用的类型就是GET。顾名思义,GET就是去服务器获取一些资源。对于访问网页来讲,要获取的资源往往是一个页面。其实也有很多其他的格式,比如说返回一个JSON字符串,到底要返回什么,是由服务器端的实现决定的。
  • 例如,在云计算中,如果我们的服务器端要提供一个基于HTTP协议的API,获取所有云主机的列表,这就会使用GET方法得到,返回的可能是一个JSON字符串。字符串里面是一个列表,列表里面是一项的云主机的信息。
  • 另外一种类型叫做POST。它需要主动告诉服务端一些信息,而非获取。要告诉服务端什么呢?一般会放在正文里面。正文可以有各种各样的格式。常见的格式也是JSON。
  • 例如,我们下一节要讲的支付场景,客户端就需要把“我是谁?我要支付多少?我要买啥?”告诉服务器,这就需要通过POST方法。再如,在云计算里,如果我们的服务器端,要提供一个基于HTTP协议的创建云主机的API,也会用到POST方法。这个时候往往需要将“我要创建多大的云主机?多少CPU多少内存?多大硬盘?”这些信息放在JSON字符串里面,通过POST的方法告诉服务器端。
  • 还有一种类型叫PUT,就是向指定资源位置上传最新内容。但是,HTTP的服务器往往是不允许上传文件的,所以PUT和POST就都变成了要传给服务器东西的方法。
  • 在实际使用过程中,这两者还会有稍许的区别。POST往往是用来创建一个资源的,而PUT往往是用来修改一个资源的。例如,云主机已经创建好了,我想对这个云主机打一个标签,说明这个云主机是生产环境的,另外一个云主机是测试环境的。那怎么修改这个标签呢?往往就是用PUT方法。
  • 再有一种常见的就是DELETE。这个顾名思义就是用来删除资源的。例如,我们要删除一个云主机,就会调用DELETE方法。

3.2 第二部分:首部字段

  • 请求行下面就是我们的首部字段。
    • 首部是key value,通过冒号分隔。这里面,往往保存了一些非常重要的字段。
  • 例如,Accept-Charset,表示客户端可以接受的字符集,防止传过来的是另外的字符集,从而导致出现乱码。再如,Content-Type是指正文的格式。例如,我们进行POST的请求,如果正文是JSON,那么我们就应该将这个值设置为JSON。
  • 这里需要重点说一下的就是缓存。为啥要使用缓存呢?
    • 那是因为一个非常大的页面有很多东西。例如,我浏览一个商品的详情,里面有这个商品的价格、库存、展示图片、使用手册等等。商品的展示图片会保持较长时间不变,而库存会根据用户购买的情况经常改变。如果图片非常大,而库存数非常小,如果我们每次要更新数据的时候都要刷新整个页面,对于服务器的压力就会很大。
  • 对于这种高并发场景下的系统,在真正的业务逻辑之前,都需要有个接入层,将这些静态资源的请求拦在最外面,架构图就像这样。
    • image
      image
  • 其中DNS、CDN我在后面的章节会讲。和这一节关系比较大的就是Nginx这一层,它如何处理HTTP协议呢?对于静态资源,有Vanish缓存层。当缓存过期的时候,才会访问真正的Tomcat应用集群。
  • 在HTTP头里面,Cache-control是用来控制缓存的。当客户端发送的请求中包含max-age指令时,如果判定缓存层中,资源的缓存时间数值比指定时间的数值小,那么客户端可以接受缓存的资源;当指定max-age值为0,那么缓存层通常需要将请求转发给应用集群。
  • 另外,If-Modified-Since也是一个关于缓存的。也就是说,如果服务器的资源在某个时间之后更新了,那么客户端就应该下载最新的资源;如果没有更新,服务端会返回“304 Not Modified”的响应,那客户端就不用下载了,也会节省带宽。
  • 目前为止,我们仅仅是拼凑起来了HTTP请求的报文格式,接下来,浏览器会把它交给下一层传输层。怎么交给传输层呢?其实也无非是用Socket这些东西,只不过用的浏览器里,这些程序不需要你自己写,有人已经帮你写好了。

04.HTTP请求发送

4.1 建立网络连接

  • 浏览器使用TCP/IP协议与服务器建立网络连接。这涉及到解析主机名为IP地址、建立TCP连接等步骤。

4.2 发送请求头

  • 浏览器将构建好的HTTP请求头发送给服务器。
    • 请求头包含了请求方法、URL、请求头字段(如User-Agent、Accept等)等信息。

4.3 发送请求体

  • 发送请求体(对于POST请求):
    • 如果请求方法是POST或其他需要发送数据的方法,浏览器会将请求体发送给服务器。请求体可以包含表单数据、JSON数据等。

4.4 等待服务器响应

  • 等待服务器响应:浏览器等待服务器对请求作出响应。

    • 在等待期间,浏览器可能会显示加载指示器,以表示请求正在进行中。
  • HTTP协议是基于TCP协议的,所以它使用面向连接的方式发送请求,通过stream二进制流的方式传给对方。当然,到了TCP层,它会把二进制流变成一个的报文段发送给服务器。在发送给每个报文段的时候,都需要对方有一个回应ACK,来保证报文可靠地到达了对方。如果没有回应,那么TCP这一层会进行重新传输,直到可以到达。同一个包有可能被传了好多次,但是HTTP这一层不需要知道这一点,因为是TCP这一层在埋头苦干。

  • TCP层发送每一个报文的时候,都需要加上自己的地址(即源地址)和它想要去的地方(即目标地址),将这两个信息放到IP头里面,交给IP层进行传输。

  • IP层需要查看目标地址和自己是否是在同一个局域网。如果是,就发送ARP协议来请求这个目标地址对应的MAC地址,然后将源MAC和目标MAC放入MAC头,发送出去即可。如果不在同一个局域网,就需要发送到网关,还要需要发送ARP协议,来获取网关的MAC地址,然后将源MAC和网关MAC放入MAC头,发送出去。

  • 网关收到包发现MAC符合,取出目标IP地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的MAC地址,将包发给下一跳路由器。这样路由器一跳一跳终于到达目标的局域网。这个时候,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是,在这个局域网上发送ARP,获得这个目标地址的MAC地址,将包发出去。

  • 目标的机器发现MAC地址符合,就将包收起来;发现IP地址符合,根据IP头中协议项,知道自己上一层是TCP协议,于是解析TCP的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个ACK,如果不是就丢弃。

  • TCP头里面还有端口号,HTTP的服务器正在监听这个端口号。于是,目标机器自然知道是HTTP服务器这个进程想要这个包,于是将包发给HTTP服务器。HTTP服务器的进程看到,原来这个请求是要访问一个网页,于是就把这个网页发给客户端。

05.HTTP返回构建

5.1 构建响应码

  • 服务器生成一个响应状态码,用于表示请求的处理结果。
    • 常见的状态码包括200表示成功,404表示未找到,500表示服务器内部错误等。

5.2 构建响应头

  • 服务器生成一些响应头,包含了一些元数据信息。
    • 响应头可以包含内容类型、内容长度、缓存控制、重定向等信息,以便浏览器正确处理响应。

5.3 构建响应体

  • 服务器生成响应体,其中包含了实际的响应数据。
    • 响应体可以是HTML文档、CSS样式表、JavaScript代码、图像文件等,具体内容取决于服务器的处理结果。

5.4 发送响应数据

  • 发送响应:服务器将生成的HTTP响应发送回浏览器。

    • 响应中包含了状态码、响应头和响应体等信息。目前响应内容一般用json来传输数据!
  • HTTP的返回报文也是有一定格式的。这也是基于HTTP 1.1的。

    • image
      image
  • 状态码会反应HTTP请求的结果。

    • “200”意味着大吉大利;而我们最不想见的,就是“404”,也就是“服务端无法响应这个请求”。然后,短语会大概说一下原因。
  • 接下来是返回首部的key value。

    • 这里面,Retry-After表示,告诉客户端应该在多长时间以后再次尝试一下。“503错误”是说“服务暂时不再和这个值配合使用”。
  • 在返回的头部里面也会有Content-Type,表示返回的是HTML,还是JSON。

  • 构造好了返回的HTTP报文,接下来就是把这个报文发送出去。还是交给Socket去发送,还是交给TCP层,让TCP层将返回的HTML,也分成一个个小的段,并且保证每个段都可靠到达。这些段加上TCP头后会交给IP层,然后把刚才的发送过程反向走一遍。虽然两次不一定走相同的路径,但是逻辑过程是一样的,一直到达客户端。

  • 客户端发现MAC地址符合、IP地址符合,于是就会交给TCP层。根据序列号看是不是自己要的报文段,如果是,则会根据TCP头中的端口号,发给相应的进程。这个进程就是浏览器,浏览器作为客户端也在监听某个端口。

  • 当浏览器拿到了HTTP的报文。发现返回“200”,一切正常,于是就从正文中将HTML拿出来。HTML是一个标准的网页格式。浏览器只要根据这个格式,展示出一个绚丽多彩的网页。

  • 这就是一个正常的HTTP请求和返回的完整过程。

贡献者: yangchong211
下一篇
1.2通过购物熟悉网络加密