Linux网络(九):从 URL 到 HTTP 报文:彻底搞懂 HTTP 请求与响应,并手写一个简单的 HTTP 服务器
2026/9/12 19:07:14 网站建设 项目流程

◆ 博主名称: 小此方-CSDN博客
大家好,欢迎来到小此方的博客。
⭐️网络系列个人专栏: 【主题曲】计算机网络
⭐️此方的GitHub: github_此方
⭐️我们思考 (Rethink) · 我们重建 (Rebuild) · 我们记录 (Record)

文章目录

  • 概要&序論
  • 一、什么是HTTP协议?
  • 二、从分析URL(网址)初步看HTTP协议
    • 2.1协议
    • 2.2域名
    • 2.3资源访问路径
      • 2.3.1在网络中,如何定义 “资源”
      • 2.3.2网络资源存放的路径
    • 2.4我们如何访问资源
    • 2.5 总结
    • Tips:urlencode和urldecode(补充内容)
  • 三、HTTP请求与响应格式
    • 3.1Http请求的格式
      • 3.1.1请求格式的内容有哪些
      • 3.1.2请求格式的细节
          • 3.1.2.1HTTP协议如何做到报头和有效载荷分离?
        • 3.1.2.2HTTP协议如何做序列化和反序列化
    • 3.2Http响应的格式
      • 3.2.1响应格式的内容有哪些
  • 四、设计一个简单的HTTP服务器——参考源码

概要&序論

Hello,大家好,我是此方。在第七期的时候,我们讲解了如何去自定义一个应用层协议,虽然我们说,应用层协议是我们程序员自己定的。但实际上,已经有大佬们定义了一些现成的,又非常好用的应用层协议,供我们直接参考使用。HTTP(超文本传输协议)就是其中之一。本文开始的连续多篇内容,我们就开始详细讲解HTTP协议。

一、什么是HTTP协议?

给一个课本定义:在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。
它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如HTML文档)。
HTTP协议是客户端与服务器之间通信的基础。客户端通过HTTP协议向服务器发送请求,服务器收到请求后处理并返回响应。HTTP协议是一个无连接、无状态的协议,即每次请求都需要建立新的连接,且服务器不会保存客户端的状态信息。

二、从分析URL(网址)初步看HTTP协议

2.1协议

前面这个https 或者说 http表示获取资源采用的协议。像一些成熟的协议,端口号都是固定的,比如:https: 443,http: 80,ssh: 22。这也印证了:0~1023的端口号不能随便用。

2.2域名

你可以简单的理解,域名就是IP地址。域名转化为IP地址访问,就是去访问这个公司的服务器。直接用这个公司的IP为什么不好?因为IP地址没有表意性。

2.3资源访问路径

2.3.1在网络中,如何定义 “资源”

先来理解一下什么是资源
你想想,人的上网行为可以概括为哪些?就两种

  1. 从远端拿下来数据。
  2. 将自己本地的数据上传到远端。

这些数据可以是什么呢?短视频、视频、网页、图片、音频…… 。没有获取它的时候,这些资源在哪里?答案是:Linux 服务器内部。以什么形式存在呢?答案是:一个文件就是“资源”。

2.3.2网络资源存放的路径

回到这里,于是我们看到,/Z2314246476?spm=1000.2115.3001.5343就可以理解为一种资源存放的路径。前面的这个“/”,就是Web根目录,注意:Web根目录不是Linux的根目录,这里必须先埋下一个伏笔。。中间的这些“/”,就是Linux的路径分隔符。资源就是服务器下对应的资源。

2.4我们如何访问资源

首先,运营商给我们建设了域名服务器。我们用浏览器输入URL访问这个域名服务器,域名服务器解析域名,返回一个IP地址。然后浏览器就可以拿着这个IP地址 + 端口号(取决于你采用的协议HTTP或是HTTPS)访问对应的服务器,根据域名后面的资源访问路径获取对应的资源。

运营商的域名服务器里存着一本庞大的“电话簿”——DNS 记录表。当你在浏览器输入域名时,服务器就会在这本“电话簿”里检索,将域名精准翻译成对应的 IP 地址。

我们去ping一个百度的网址,可以看到正在 Ping www.a.shifen.com [2409:8c54:870:187:0:ff:b0d9:bb1c] 具有 32 字节的数据:,这里面的[2409:8c54:870:187:0:ff:b0d9:bb1c] 就是IP地址,IP地址+端口号,也就是协议+域名就可以访问目标服务器。

Tips:为什么这个IP地址看起来这么奇怪?因为这是IPv6的地址。我们平常看到的是IPv4

PS C:\Windows\System32\WindowsPowerShell\v1.0>pingwww.baidu.com 正在 Ping www.a.shifen.com[2409:8c54:870:187:0:ff:b0d9:bb1c]具有32字节的数据: 来自2409:8c54:870:187:0:ff:b0d9:bb1c 的回复: 时间=551ms 来自2409:8c54:870:187:0:ff:b0d9:bb1c 的回复: 时间=529ms 来自2409:8c54:870:187:0:ff:b0d9:bb1c 的回复: 时间=352ms 来自2409:8c54:870:187:0:ff:b0d9:bb1c 的回复: 时间=597ms2409:8c54:870:187:0:ff:b0d9:bb1c 的 Ping 统计信息: 数据包: 已发送=4,已接收=4,丢失=0(0% 丢失), 往返行程的估计时间(以毫秒为单位): 最短=352ms,最长=597ms,平均=507ms PS C:\Windows\System32\WindowsPowerShell\v1.0>

做一些历史补充,以下框出来的两个字段曾经有,现在已经被废弃了。

2.5 总结

从 HTTP 的角度来看,“资源”本质上就是存储在 Linux 服务器特定路径下的文件。
我们在 URL 中看到的协议与端口号(http/https:port)域名(映射具有唯一性的 IP 地址)以及路径(目标机器上特定路径的文件),这三者共同构成了全网内唯一的文件定位。
因此,超文本传输协议的本质就是用来传递文件的,其底层依然是基于 Socket 实现的网络通信!!!!

Tips:urlencode和urldecode(补充内容)

我们尝试去搜索一下这个内容:hello: //@world

可以看到,在搜索框中输入的特殊字符在 URL 中变成了像%20%3A%2F%40这样的一串字符。

:/@以及空格等字符,在 URL 中具有特殊的用途或分隔含义。如果这些字符直接出现在 URL 的参数中,会导致客户端或服务器在解析 URL 时发生混淆,进而引发解析失败。

为了避免歧义,客户端(如浏览器)在向服务器发送请求前,会自动将 URL 中的特殊字符转码为十六进制形式,这个转码的过程就称为urlencode。当服务器接收到请求后,再将其还原为原始字符,这个解码的过程则称为urldecode
这种由浏览器负责 urlencode 编码、服务器负责 urldecode 解码的交互模式,正是典型的 B/S(Browser/Server)架构模式。我们以前写的是C/S。

转义规则:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式

三、HTTP请求与响应格式

3.1Http请求的格式

3.1.1请求格式的内容有哪些

找到了一个HTTP请求报文,我们来分析一下。

  • 首行: [方法] + [url] + [版本]。
  • Header: 请求的属性, 冒号分割的键值对; 每组属性之间使用 \r\n 分隔;遇到空行表示 Header 部分结束。
  • Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在,则在Header中会有一个Content-Length属性来标识Body的长度。(后面详细讲)

HTTP的底层是TCP,我们在后面的代码中会体会到。

把上面的报文抽象一下,我们会得到这样一个结构图:

3.1.2请求格式的细节

整个 HTTP 请求报文在网络传输中,本质上就可以被理解为一个具有多行的字符串。

3.1.2.1HTTP协议如何做到报头和有效载荷分离?

HTTP 协议以空行(\r\n)作为报头与有效载荷的分隔符。在解析报文时,系统按行读取,当读取到一个只有换行符的空行时,就意味着请求报头(Header)部分结束,紧接着后续的内容即为有效载荷(Body)。

3.1.2.2HTTP协议如何做序列化和反序列化

HTTP 协议的序列化与反序列化过程非常直接,它并没有依赖任何复杂的第三方库,而是直接使用特殊字符进行字符串的拼接与切割。在发送端,将内存中的结构化请求数据按规范拼接为字符串(序列化);在接收端,则通过匹配特殊字符将该字符串重新解析提取为结构化对象(反序列化)。

3.2Http响应的格式

3.2.1响应格式的内容有哪些

找到了一个HTTP响应报文,我们来分析一下。

  • 首行: [版本号] + [状态码] + [状态码解释]。
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\r\n分隔;遇到空行表示Header部分结束。
  • Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中。

四、设计一个简单的HTTP服务器——参考源码

都是手写代码,可能会有bug,如果有,非常欢迎大佬指出私信。量真的太大了,我把仓库贴一下:(目前仓库还在建设中,Readme还没有写。)Konata’s Network-Programming


好的本期内容就到这里,如果对你有帮助,还不要忘记点赞三联支持。我是此方,我们下期再见。bye!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询