「网络通信」HTTP 协议

HTTP

🍉简介

HTTP 协议全称为超文本传输协议,超文本比文本更加强大,它不仅包含字符串,还可以携带一些图片、特殊格式等

HTTP 最主要的应用场景就是网站。浏览器和服务器、客户端和服务器之间传输数据的协议,很可能就是 HTTP


🍉抓包工具

抓包工具本质上是一个代理程序,能够获取到网络上传输的数据并显示出来,从而给程序员提供一些参考,在后面介绍 HTTP 报文格式的过程中,会频繁用到抓包工具,这里我们使用 fiddler,它专注于 HTTP 的抓包

打开一个网站,浏览器和服务器之间会进行多次 HTTP 交互,其中第一次交互拿到的是这个页面的 html

选中这个请求并双击,可以看到明细:

点击 RAW,可以查看 HTTP 请求的原始数据
下面是请求的原始数据

再来看下响应的原始数据


为了节省带宽,一般响应数据会被压缩,对上述响应解压缩得到:


🍉报文结构

🍌请求

HTTP 请求包含 4 个部分

  1. 首行
  1. 请求头:由若干个键值对组成,每个键值对占一行, 键和值之间使用 : 分割
  2. 空行:请求头的结束标记
  3. 正文(body):http 的载荷部分,有的 http 请求有 body,有的没有

🍌响应

HTTP 响应的基本格式也是分为四个部分

  1. 首行
  1. **响应头:这里是按照键值对的形式来组织内容
  2. 空行
  3. 响应正文(body):响应的载荷是 html**

🍌URL

URL 全称为唯一资源定位符,用来描述一个网络上资源的位置

一个 URL 的完整结构如下:

🥝URL encode

query string(查询字符串)里是自定义的键值对,而在 URL 中,有些特殊符号,比如 / : ? @ 等都是有特定的含义,如果 query string 中也包含同样的符号,可能会使服务器 / 浏览器解析失败,比较靠谱的方法就是对上述符号进行转义(就像 C语言中用 printf 打印一些特殊符号一样,需要转义)。

除了这些特殊符号,汉字也要进行转义,因为汉字的 utf8 / gbk 等编码值中可能某个字节恰好和某个符号的 ASCII 码值一致

下面举个例子,比如搜索 C++:


🍌方法

有两个典型的使用 POST 的场景:登录和上传

以登录为例,在一个网站输入账号密码登录后抓包得到的数据报的 body:

这里有一个比较经典的面试题:

GET 和 POST 有什么区别

GET 和 POST 本质上没有区别。使用 GET 的场景也可以替换为 POST;使用 POST 的场景也可以替换为 GET。这取决于代码是怎么写的,尤其是服务器和客户端都是自己实现的情况下

但是这两者在使用习惯上还是有区别的:

  1. GET 习惯于把数据放到 URL 的 query string 中;POST 习惯于把数据放到 body 中
  2. 语义上的区别。标准文档中,GET 的语义是用来获取数据;POST 的语义是给服务器传输数据。当然实际使用并不拘泥于上述要求
  3. 关于幂等性。标准文档中建议 GET 请求实现成幂等的;POST 则没有要求。当然 GET 在实际开发中也不一定得实现成幂等
    这里的"幂等"源于数学术语,如果每次输入的内容一定,输出的结果也一定,那就是幂等;反之,若输入内容一定,但输出不一定,则不是幂等。在计算机中,如果某个操作是幂等的,那就可以进行缓存

🍌报文字段

🥝Host

表示服务器主机的地址和端口


🥝Content-Length & Content-Type

这两个字段分别表示 body 中数据的长度和请求的 body 中的数据格式

HTTP 底层也是基于 TCP。连续传输多个 HTTP 数据报的话,接收方这边的接收缓冲区里就会积累多个包的数据,应用程序在读取这些数据时需要明确包与包之间的边界。通过长度可以解决粘包问题


🥝User-Agent(UA)

UA 描述了操作系统和浏览器的信息,这两个其实就是在描述用户使用什么样的设备上网

它里面包含了系统信息,这就可以判定系统是 PC 的系统,还是移动端的系统,此时可以根据这个信息来返回不同的页面
比如在手机浏览器的设置中手动把 UA 修改为 PC 的 UA,那么就可以访问电脑版的网页了


🥝Referer

描述当前这个页面从哪儿来,类似上层目录,所以直接在浏览器输入 URL 的路径或从收藏夹中打开的网页都是没有 referer 的


🥝Cookie

Cookie 是报头中一个非常重要的属性,它本质上是浏览器本地持久化存储数据的机制

操作系统提供了 api 操作文件,浏览器作为电脑上的一个程序,可以调用这些 api 来读写本地磁盘文件。而浏览器上运行的网页,理论上也是可以通过浏览器提供的 api 来读写本地文件,但是为了保证安全性,浏览器禁止这种做法,也就是说它没有给网页提供这样的 api。不然有些不法分子搞一些恶意网站,你点进去之后它就会把你电脑上的文件删掉,这样势必会造成巨大损失!

不过有些网站需要把一些信息保存到浏览器这边,比如登录界面需要保存用户的身份信息。所以浏览器给网页提供了这样的 api:可以有限度地存储数据,但不能随意访问文件系统

Cookie 就是一种经典的存储数据的机制,它将存储的数据按照键值对的形式存储起来,其中键值对是由程序员自定义的,和 query string 差不多,因此不同网站的 Cookie 都是不一样的

HTTP 请求中的 Cookie 字段就是把本地存储的 Cookie 信息发送到服务器。相应地,HTTP 响应中会有一个 Set-Cookie 字段,这个是服务器告诉浏览器要在本地保存哪些信息

通常在首次访问 / 登录成功之后服务器会把数据返回给浏览器,然后 Cookie 会以域名为维度存储在浏览器本地主机的硬盘上,比如浏览器访问 Gitee,就有一组 Cookie,访问 B 站,又有一组 Cookie,这些 Cookie 之间互不冲突,后续每次访问服务器都会带上对应网站的 Cookie

不同的客户端保存的 Cookie 是不同的,即使是同一台主机,使用不同的浏览器,Cookie 大概率也是不同的


Cookie 用途就是在客户端保存数据,其中保存的数据最主要是用户的身份标识,这样服务器就可以通过标识来区分用户。它一般不会保存其他业务数据,这些数据存在服务器,通过 Cookie 中的身份标识可以找到这些数据

有个典型的场景:在某个页面登录之后,下次登录就不用再输入账号密码,因为首次输入账密后这些信息就会保存在磁盘,下次进入网页时就会先从本地读取磁盘拿到账密。发送 HTTP 请求后服务器收到 Cookie 中的用户信息后就通过身份验证了,所以不用再手动输入账密

补充:页游中的账号密码等信息一般不是放在 Cookie 中的,因为浏览器保存的密码都是明文密码,放到 Cookie 中不安全


🍉状态码

🍌类别

🍌常见状态码

  1. 200 OK
    打开 Fiddler,放眼望去基本都是 200,它表示请求已经成功处理
  2. 404 Not Found
    这个也很常见,Not found 表示访问的资源没找到,此处的资源指的是 URL 中的路径
    比如输入一个不存在的网址:
  1. 403 Forbidden

    表示请求的资源没有权限访问

  2. 405 Method Not Allowed

    如果你的服务器只支持 GET 请求,但是你发了一个 POST 请求,那就会出现这个状态码

  3. 500 Internal Server Error

    表示服务器内部错误,遇到这种情况可能是服务器挂了

  4. 504 Gateway Timeout

    访问服务器超时了,这可能是服务器挂了,也可能是网断了

  5. 302 Move temporarily

    临时重定向,表示资源临时移动到新的位置。除了 302,301 也表示重定向,不过它是永久性的。重定向的时间会影响浏览器的缓存,如果是永久性的,那么浏览器会把重定向的结果记录下来,后续再次访问就会直接访问重定向的目标地址,不用多一次跳转了;而如果是临时性的,那就不太方便缓存了

    重定向报文的响应中会有一个特殊的 header:Location,它描述了重定向的目标地址在哪儿

相关推荐
P.H. Infinity6 分钟前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天10 分钟前
java的threadlocal为何内存泄漏
java
caridle21 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^26 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋330 分钟前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花34 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端37 分钟前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan44 分钟前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫