HTTP协议从基础到实战全解析

文章目录

应用层核心:HTTP协议从基础到实战全解析

在实际开发中,我们偶尔会定制私有网络协议(比如 len+JSON格式的自定义协议,文章 中使用该方法),但实际中更多依赖成熟的通用协议------HTTP(超文本传输协议),与我们自己定制的协议类似,只不过HTTP协议功能更多,更复杂。本文将详细介绍HTTP协议。

本文暂时不进行socket编程,只讲解协议,在后期会更新代码编程教学

一、HTTP协议基础认知

1. 什么是HTTP?

HTTP(HyperText Transfer Protocol,超文本传输协议)定义了客户端(浏览器、手机APP、各类终端程序)与服务器之间的通信规则,核心目标是实现超文本的传输与交换。我们使用的浏览器就是一些厂商做出来的额客户端,可以将HTTP协议传输回来的超文本进行解析,渲染,形成我们所看到的网页,视频等。

超文本:不限于纯字符文本,还包含视频、图片、音频等各类文件资源;-

底层支撑:HTTP基于TCP协议实现可靠的字节流传输,是其能保证数据完整传输的核心。

2. 网络通信的核心:资源

​ 网络通信本质上是进程间通信(服务器上的某一个进程与客户端上的某一个进程),进程间通信本质上是数据的读写,也就是IO问题。在访问网络时,我们做的无非也是获取信息或者推送信息,我们在网络通信中所获取的超文本信息(网页,图片,视频,音频等)都是资源,在我们访问之前(获取到之前)这些资源都是在服务器中存储的

​ 许多的后端服务器都使用的linux操作系统,linux操作系统下一切皆文件,当客户端向服务器发起获取自愿的请求时,在服务器端首先要找到该资源才可以进行回应,因此在URL中带有路径,就是我们所要资源(文件资源)的路径,该路径在该机器中也一定是唯一的,

二、URL:互联网资源的"唯一定位符"

URL(Uniform Resource Locator,统一资源定位符)也叫超链接(俗称"网址"),其核心作用是精准定位互联网中的唯一资源。

1. URL的核心逻辑

IP地址定位互联网中的唯一主机,路径定位主机内的唯一文件资源,二者结合即可标识互联网中唯一的文件资源------这也是URL被称为"统一资源定位符"的原因。

2. URL的端口

成熟协议与端口号强绑定,HTTP默认使用80端口,HTTPS默认使用443端口。因此URL中通常省略端口号,浏览器发起请求时会自动拼接对应协议的默认端口(如访问http://www.example.com时,实际访问的是http://www.example.com:80,即访问80号端口)。

3. 完整URL的结构拆解

以示例 http://www.example.com:8080/products/index.html?category=books\&page=2#introduction 为例,URL各部分的含义如下:

组成部分 示例内容 核心说明
协议(Scheme) http:// 指定通信协议(如HTTP/HTTPS/FTP等),决定客户端与服务器的通信规则;
主机(Host) www.example.com 服务器的域名/IP地址,会被包含在HTTP请求的Host头字段(如Host: www.example.com);
端口(Port) :8080 服务器监听HTTP请求的端口,省略时使用协议默认端口(HTTP=80、HTTPS=443);
路径(Path) /products/index.html 资源在服务器的具体位置,是HTTP请求行的核心(如GET /products/index.html HTTP/1.1);
查询字符串 ?category=books&page=2 以?开头的键值对参数,多参数用&分隔,向服务器传递动态参数(分页、筛选等);
片段(Fragment) #introduction 以#开头,仅浏览器端生效(定位页面锚点),不会发送到服务器

4. 实战案例:搜索引擎URL拆解

以必应搜索"linux"的URL https://cn.bing.com/search?q=linux\&form=QBLH\&mkt=zh-CN 为例,拆解核心部分:

  • 协议:https://(安全版HTTP,加密传输);

  • 子域名+主域名:cn.bing.com(cn指向中国区,bing.com为必应主域名);

  • 路径:/search(服务器处理搜索请求的核心路径);

  • 查询字符串:

    • q=linux:q(query)为搜索关键词参数,值为"linux";

    • form=QBLH:标识搜索请求的来源表单;

    • mkt=zh-CN:指定"中文-中国"本地化配置。

5. URL的关键补充

URL编码(URLDecode)

若参数包含空格、汉字、特殊符号(&或?等),会被转为%XX格式(如空格→%20、"linux command"→q=linux%20command),避免URL解析错误。

三、HTTP的请求与响应:标准化通信格式

HTTP遵循"请求-响应"模型,客户端发送请求、服务器返回响应,二者均有严格的格式规范。

1. HTTP请求格式

HTTP请求以行为单位组织,核心分为四部分:

请求行:格式为请求方法 URI HTTP版本(如GET /index.html HTTP/1.1),包含核心请求指令;

    • URI:通常为URL的路径部分,标识要访问的资源;

      • HTTP版本:如HTTP/1.0/HTTP/1.1/HTTP/2.0,区分协议功能支持;
  • 请求报头:携带客户端信息(浏览器版本、系统类型)、请求属性(如Host/Content-Length);

  • 空行:强制分隔报头与正文,是HTTP格式的必要组成;

  • 请求方法:包括GET、POST、HEAD、DELETE等,定义对资源的操作类型;

  • 请求正文:POST方法专用(传递大体积参数),GET方法无正文(参数通过URL传递)。

2. HTTP响应格式

HTTP响应与请求格式对应,核心分为四部分:

  • 状态行:格式为HTTP版本 状态码 状态描述(如HTTP/1.1 200 OK);
  • 响应报头:标识响应属性(如Content-Type/Content-Length),可省略;
  • 空行:分隔报头与正文;
  • 响应正文:URI对应的实际资源(HTML、图片、视频等)。

举例:

当我的服务器上有show.html这样的超文本资源时,并且有响应程序,那么就可以进行访问(平时所访问的网站也是这样的道理)。

在浏览器输入相应的URL,即 http://127.0.0.1:8888/show.html (IP为127.0.0.1,是因为我在本地测试,使用的本地回环IP,他会走一遍协议栈,在返回本主机。我使用的是8888端口,如果部署的服务需要公开,那么就要绑定80端口,因为别人会默认使用80端口,而我自己就随便使用了)

点击回车,即可发起请求,在我的服务器上将收到下面这样的HTTP请求:

我的程序里面会构建这样的HTTP响应,响应正文是将文件show.html的内容直接拷贝即可,因为是超文本信息,直接传输即可。

其中正文是超文本数据,即HTML语言所编写的前端程序,我不太懂前端,这是AI生成的,浏览器会将该HTML语言渲染为我们所看到的网页,如下:

3. 核心报头

  1. Content-Length:有正文时必填,标识正文字节长度,是报头与正文分离的核心依据。
  2. Content-Type:标识响应正文的数据类型(如text/html表示HTML文本、image/jpeg表示JPG图片),是浏览器解析资源的核心依据。
  3. Host:客户端告知服务器,所请求的资源是在哪个主机的哪个端口上。
  4. User-Agent:声明用户的操作系统和浏览器版本信息。
  5. Referer:指示当前页面是从哪个页面跳转过来的。
  6. Location:搭配3xx状态码使用,告诉客户端接下来要去哪里访问。
  7. Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。

4.补充概念

Web根目录

服务器在响应时,HTTP响应报文完全由程序员在应用层通过代码构建,而非操作系统自动生成。因此,响应报文中的所有信息都需要手动填入,包括正文内容。正文通常是超文本信息,需要通过二进制读取方式将其完整写入响应报文的正文部分。为了便于管理不同资源,我们会在服务器工作路径下创建一个名为"webroot"的目录,将所有超文本资源集中存储于此。当用户请求资源时,服务器会在请求路径前自动拼接该目录路径,以实现资源的统一管理与访问。

默认首页

当客户端仅访问根路径(/)时,服务器不应返回Web根目录的全部内容,而需自动拼接默认首页(如index.html)并返回该页面。这一行为需由服务器代码主动实现,而非服务器软件自动完成。

浏览器加载网页的过程

浏览器首先请求并获取主页的HTML文档,随后自动扫描HTML中的标签(如图片、视频、样式表等),并针对这些附属资源发起额外的HTTP请求,最终将所有获取的资源在客户端拼接、渲染成完整的网页。

四、HTTP核心特性:版本、状态码、请求方法

1. HTTP版本

协议版本区分功能支持:新版本通常新增/修改功能,旧版本无法使用新版本特性,因此请求/响应中必须携带版本号(如HTTP/1.1)。主流版本为HTTP/1.1,此外还有HTTP/1.0(早期版本)、HTTP/2.0(性能优化版)。

2. HTTP状态码

状态码是服务器返回的"响应状态标识",核心分类及含义如下:

状态码分类 含义 典型场景
1xx 信息类状态码(临时响) 100 Continue(继续请求)
2xx 成功类状态码 200 OK(请求成功)
3xx 重定向类状态码 301 永久重定向、302 临时重定向
4xx 客户端错误状态码 404 Not Found(资源不存在)
5xx 服务器错误状态码 500 Internal Server Error(服务器异常)
重定向的两种类型
  • 临时重定向(302):每次访问旧地址,服务器返回新地址,客户端始终先访问旧地址;

  • 永久重定向(301):客户端(如搜索引擎)首次重定向后,更新本地记录,后续直接访问新地址(常用于网站换域名)。

如下图所示:

请求和响应数据如下:

永久重定向使用场景:

​ 普通用户通常是通过关键词搜索来寻找目标网站,然后点击搜索结果进行访问,通常是浏览器提供的标签,点击标签就会跳转访问到对应的网站。这些标签如何来呢?在后台,浏览器(或搜索引擎)会通过持续爬取网页来收集和存储网站信息(主要是域名和关键词),以便在用户搜索时提供对应的结果标签(内含域名)。

​ 如果网站已更换域名,但搜索引擎中仍保留着旧域名的链接,用户在点击该链接时,会经历一次重定向跳转到新域名。此时,浏览器(或搜索引擎)会识别出这是一个永久重定向,并随之更新其内部存储的链接,将旧域名替换为新域名。此后,当用户再次搜索或访问该网站时,浏览器就会直接使用新的域名,不再经过旧的链接跳转。

请求方法定义了客户端对服务器资源的操作类型,核心方法及特性如下:

方法 核心用途 传参方式 特性
GET 获取静态资源(网页、图片) URL查询字符串 参数暴露、体量小、私密性差
POST 提交数据(表单、大参数) 请求正文 参数隐藏、体量大、相对私密
HEAD 仅获取响应报头(无正文) 同GET 快速校验资源状态
DELETE 删除服务器资源 URL/正文传参 操作服务器资源
GET vs POST
  • GET:适合"读操作",参数暴露在URL中,传输体量有限;

同时,服务器将收到如下数据

  • POST:适合"写操作",参数在正文传输,体量无明显限制;

POST方法参数在正文,相对于GET方法较为安全,但是两者本质都不安全,因为是明文传输,被抓包后就可以直接看到。想要更好的安全性可以使用HTTPS协议,是加密的协议,与HTTP类似但是更安全。

前端提交方式

前端可通过form表单提交请求,默认使用GET方法;若需使用POST,需在表单中显式指定方法,参数会通过请求正文传递。

前文中展示的网页代码:

若要使用post方法提交表单,则将method = "get"改为 method = "post"

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>简单网页 - 带表单</title>
</head>
<body>
    <h1>欢迎来到我的网站</h1>
    <p>这是一个简单的HTML页面示例。</p>
    <p>今天天气不错!</p>
    <ul>
        <li>第一个项目</li>
        <li>第二个项目</li>
        <li>第三个项目</li>
    </ul>
    
    <hr>
    
    <h2>简单的联系表单</h2>
    <form action="/show.html" method="get"> 
        <p>
            <label for="name">姓名:</label><br>
            <input type="text" id="name" name="name">
        </p>
        <p>
            <label for="email">邮箱:</label><br>
            <input type="email" id="email" name="email">
        </p>
        <p>
            <label for="message">留言:</label><br>
            <textarea id="message" name="message" rows="4" cols="40"></textarea>
        </p>
        <p>
            <input type="submit" value="提交">
            <input type="reset" value="重置">
        </p>
    </form>
    
    <p><small>注意:这是一个示例表单,提交后不会有实际效果,除非您设置了相应的后端处理程序。</small></p>
</body>
</html>

五、Cookie与Session:解决HTTP无状态问题

HTTP协议本身是无状态、无连接的:服务器不记录客户端的历史访问记录,每次请求都是独立的。

有些网站的资源在访问时,需要进行身份识别,分类响应。比如视频网站,有的视频需要会员才可以观看,有的则不需要,客户端在请求时,服务器必须能正确识别身份才可以响应请求。而HTTP协议是无状态,无链接的,他不知道用户此时是什么身份,此时就要用到cookie和session技术(登录会话管理),它可以让用户登陆一次,在关闭网页后一段时间内仍然可以保持登陆状态

1. HTTP无状态的体现

客户端多次请求相同资源,服务器会重复响应,无法识别"该客户端是否曾访问过",即无法关联多次请求的用户身份。

2. Cookie技术

Cookie是存储在客户端的用户信息,核心原理如下:

登录阶段:用户首次登录后,服务器在响应头中携带Set-Cookie的报头(相当于服务器向客户端写入信息),浏览器识别后保存Cookie;

访问阶段:设置cookie成功后,浏览器会自动的将用户基本信息作为http请求的一部分进行拼接,这样服务器就可以对每次请求进行身份识别,实现资管推送的管理,直到该cookei失效

设置成功如下图:

之后,客户端的请求报文中会自动携带cookie数据,如下图

那么浏览器将cookie信息保存在那里呢?

  1. 内存级(浏览器关闭后,cookei失效)

  2. 文件级(在浏览器自己的工作目录下保存在文件中,浏览器关闭后在打开,可以读取文件,将cookie信息写入内存,访问服务器时进行携带信息)

  • 补充:Cookie可设置过期时间、提交路径,支持多条Cookie同时设置(添加多行cookie响应报头),但单独使用存在安全风险,且存储容量有限(仅几KB)。

完整的设置cookie响应报头格式:

cpp 复制代码
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<expiry-date>; Max-Age=<max-age-in-seconds>; Domain=<domain-value>; Path=<path-value>; Secure; HttpOnly; SameSite=<same-site-value>

其中,只有< cookie-name>=< cookie-value>是必需的,其他属性都是可选的。

各属性说明:

  1. < cookie-name>=< cookie-value>:Cookie的名称和值。
  2. Expires:Cookie的最长有效时间,形式为符合HTTP-date规范的时间戳。例如:Expires=Wed, 21 Oct 2015 07:28:00 GMT
  3. Max-Age:Cookie从设置开始计时的生存时间,单位为秒。如果同时设置了Expires和Max-Age,Max-Age优先级更高。
  4. Domain:指定Cookie可以送达的主机名。如果没有指定,默认为当前文档访问地址中的主机部分(不包含子域名)。如果指定了Domain,则一般包含子域名。
  5. Path:指定一个URL路径,这个路径必须出现在要请求的资源的路径中才可以发送Cookie首部。字符%x2F(即"/")用作文件夹分隔符,子文件夹也会被匹配到。
  6. Secure:一个带有安全属性的Cookie只有在使用SSL和HTTPS协议的时候才会被发送到服务器。
  7. HttpOnly:设置后,无法通过JavaScript的Document.cookie API访问Cookie,这有助于防范跨站脚本攻击(XSS)。
  8. SameSite:允许服务器设定何时发送Cookie,以防止跨站请求伪造攻击(CSRF)。可选值:Strict, Lax, None

完整报头示例:

cpp 复制代码
Set-Cookie: user_id=12345; Max-Age=2592000; Expires=Wed, 31 Dec 2025 23:59:59 GMT; Path=/; Domain=.example.com; Secure; HttpOnly; SameSite=Lax

3. Session技术

光有cookie不安全,因为cookie在报文中明文保存,别人抓包了会泄露数据,因此引入了Session技术。

Session是服务器端的会话管理技术,解决Cookie的安全性和容量问题,核心原理如下:

首次访问

​ 服务器生成唯一sessionid,通过Set-Cookie写入客户端;同时服务器将用户信息直接存储在服务器上,不再通过cookie写入客户端,而是维护sessionid与用户信息的映射关系,;

后续访问

​ 客户端请求时携带sessionid,服务器通过该ID匹配用户信息,实现身份识别;

优势

​ 用户核心信息存储在服务器端,无需将用户数据在网络中传输,只传输sessionid,更安全,且服务器上无Cookie的容量限制。

相关推荐
小白同学_C2 小时前
Lab2-system calls && MIT6.1810操作系统工程【持续更新】
linux·c/c++·操作系统os
物理与数学2 小时前
linux内核 struct super_block
linux·linux内核
Getgit2 小时前
Linux 下查看 DNS 配置信息的常用命令详解
linux·运维·服务器·面试·maven
漂洋过海的鱼儿2 小时前
设计模式——EIT构型(三)
java·网络·设计模式
数通工程师3 小时前
企业级硬件防火墙基础配置实战:从初始化到规则上线全流程
运维·网络·网络协议·tcp/ip·华为
血色橄榄枝3 小时前
03 基于Flutter集成网络请求On OpenHarmony
网络·flutter
jojo_zjx3 小时前
GESP 24年12月2级 数位和
c++
自由的好好干活3 小时前
PCI9x5x驱动移植支持PCI9054在win7下使用3
c++·驱动开发
zhangrelay3 小时前
Linux(ubuntu)如何锁定cpu频率工作在最低能耗模式下
linux·笔记·学习