HTTP请求与应答-URL全网唯一文件路径报文结构与短连接

HTTP 请求与应答:URL 全网唯一文件路径、报文结构与短连接

我的github:(https://github.com/xcx55/ubuntu-linux-project)

感谢各位大佬参观我的github!!

源笔记:http2(26-9-8)、http4-别人的应用层协议(26-9-11)、http5 请求报文结构(26-9-12)、字节流数据包两个的区别

上一篇认识了 HTTP 的名字和 DNS,这一篇拆它的真身:一个 URL 到底由什么组成、请求和应答报文长什么样、HTTP 请求的本质为什么是"发文件"。手搓协议攒下的眼光全用上了------协议发来发去就是一个"有结构的字符串"。

一、URL 完整拆解:全网唯一文件路径

一个完整的 URL 长这样:

复制代码
http://user:pass@www.example.jp:80/dir/index.htm?uid=1#ch1
└─协议┘└─登录信息─┘└──服务器地址──┘└┘└─文件路径─┘└查询┘└片段┘
 方案名   (认证,一般省略)               端口号  带层次     字符串  标识符

逐段看:

  • 协议方案名 :http 或 https;
  • 登录信息(认证) :user:pass@------一般省略不写;
  • 服务器地址:域名或 IP;
  • 服务器端口号 :一般服务端 HTTP 协议绑定的端口号都是 80,默认省略;
  • 带层次的文件路径 :/dir/index.htm;
  • 查询字符串 :?uid=1,传参用的;
  • 片段标识符 :#ch1。

网页的本质就是一个文件

学了前端就知道:网页的本质就是一个文件,申请网页就是申请文件 。那么怎么保证找到对应主机的这个文件?靠 Linux 的老朋友------文件路径!

前面依靠 IP 地址 + 隐藏端口号定位主机,主机内靠路径定位文件。串起来:

ip 唯一 → port 主机唯一 → 主机内路径唯一 → HTTP 本质:全网唯一的文件路径!

所以 HTTP 协议的本质就是 IO。给资源就是给 URL,URL 后面那一串本质就是 IO。

URL 与 URI

  • URL :统一资源定位符------定位,就是能找到它(笔记里的比方:学号可以唯一定位到一个学生,学号就可以叫做 URL);
  • URI :统一资源标识符------标识,范围更宽;
  • URL 本身就是 URI。

URL 传参与特殊符号编码

想给服务器传参?就是 URL 传参 ------百度搜索框里敲的内容,全被拼进了搜索路径(?wd=new%20year&...)。

约束来了:URL 传参传的东西不能干扰对 URL 的解析,但又必须传参 。怎么办?对特殊符号(+、/、.、空格等)进行编码 ------比如空格变 %20。你搜索时 URL 里那串乱码,就是这么来的。

二、两个视角:结构体还是字符串?

同一个 HTTP 协议,两个视角看它:

  • 发送者(客户端)视角 :HTTP 协议是一系列结构体进行封装和 JSON 加包------封装过的结构体资源数据,Kv 直接 k、v 序列化组合;
  • 接收者(服务端)视角 :HTTP 协议是一种具有层次的 string ,以 \n 为分隔符。

而 HTTP 的一个独特点:它是以行为单位、不依赖任何第三方库的协议(没有使用 JSON) 。为什么不用 JSON?降低用户使用 HTTP 的成本------不用引库,拿到的就是纯文本行,string 拆分就能解析。

三、读取完整性:又是那个 while 循环

TCP 是面向字节流 的:发来的数据数量未知、断断续续、发送和接收次数不匹配------不像 UDP 面向数据报,面向信件,发来三封就得到三封,消息天然完整。

所以 HTTP 的接收方必须自己回答两个问题:1、怎么保证读取完整?2、怎么反序列化?

答案和手搓协议时一模一样:

  • 必须读取到 \r\n(空行),否则 break------TCP 协议再次读取,while 循环,直到读取成功;
  • 读取完整的保证,就是靠报头的循环(应用层的完整);
  • 反序列化你自己都知道------string 的拆分。

第一层攒字节、第二层切报文,手搓 len\r\n value \r\n 时练的两层循环咬合,在 HTTP 里原样复现。

四、请求报文:请求行 + 报头 + 空行 + 正文

复制代码
HTTP REQUEST
┌────────────────────────────────────────┐
│ 请求行: 请求方法 空格 URI 空格 HTTP版本 换行符 │ ← GET /a/b/c.html HTTP/1.1
├────────────────────────────────────────┤
│ 请求报头: Key:[空格]Value 换行符            │ ← 一行一条,可有多条
│          Key:[空格]Value 换行符            │
│          ...                            │
├────────────────────────────────────────┤
│ 空行: 换行符                     ← 必须!  │
├────────────────────────────────────────┤
│ 请求正文: DATA                   ← 可选的  │
└────────────────────────────────────────┘

请求行的三个字段

  1. 请求方法 :一般就两种------GET (一般是获取)和 POST(一般是上传);
  2. URI:ip 和端口以及路径------找到唯一主机的唯一文件;
  3. HTTP 版本 :最常用 http1.1。注意携带的是客户端的 HTTP 版本。

为什么协议要有版本?想想 App 怎么知道软件需要更新------版本被以配置文件的方式记录下来。用版本检测可以规避问题、新增不同的功能、支持不同的功能。

报头与空行

报头是 Key: Value 结构,一行一个,装的是"本次 client 需求的信息和服务端的相对信息"(Host、Connection、User-Agent、Cookie 等等)。报头和正文之间依据空行隔开 ------这个空行就是上一节"读到 \r\n 才算完整"的那个 \r\n,也是报头结束的标志。

分割报文,还是尽量先广度后局部:先按空行切出报头和正文,再按行拆报头,最后按结构拆请求行。

一个真实的请求

复制代码
POST http://job.xjtu.edu.cn/companyLogin.do HTTP/1.1
Host: job.xjtu.edu.cn
Connection: keep-alive
Content-Length: 36
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) ...
Cookie: JSESSIONID=D628A75845A74D29D991DB47A461E4FC; ...

username=hgtz2222&password=222222222

登录场景:正文里带着账号密码(这就是 POST 上传),报头里 Content-Length 告诉你正文多长,Cookie 带着会话状态。

五、应答报文:状态行是灵魂

HTTP 不像我们的自定义协议那样 request 和 response 共用一套格式------它的请求和应答是不一样的! (回想网络计算器:去是 size+两个数+操作,回来是 size+一个结构体,格式本来就允许不同。HTTP 做了更高级的封装,前字符串进行了统一,但应答有应答自己的行。)

复制代码
HTTP RESPONSE
┌────────────────────────────────────────┐
│ 状态行: HTTP版本 空格 状态码 空格 状态码描述 换行符 │
├────────────────────────────────────────┤
│ 响应报头: Key:[空格]Value 换行符            │
├────────────────────────────────────────┤
│ 空行: 换行符                              │
├────────────────────────────────────────┤
│ 响应正文: DATA(视频/文件/文章/css/js 等不同类型文件)│
└────────────────────────────────────────┘
  • 状态行 :HTTP 版本(这次是 httpserver 的版本)+ 状态码 + 状态码描述;
  • 状态码 :但凡网络还在、客户端发出来了请求,server 必须回复应答 ------请求出错了怎么办?比如 404 NOT FOUND。依据 server 的状态码,客户端为用户或者 server 采取措施;
  • 状态码描述:对状态码的描述,人类可以识别的文字(404 和 NOT FOUND 一起表示请求状态)。

六、HTTP 请求的本质:把 Linux 目录下的文件发给客户端

把所有封装拆掉,看到底:

HTTP 超文本请求的本质:起始就是通过网络服务器,把 Linux 机器上特定目录下的文件,以 http 应答的方式返回给 client(浏览器或者 app)。

  • server 端源代码的地方,就是根目录的地方;
  • 一般来说我们请求直接写 www.xxx.com/,后面是客户端主动加上 index.html 这个文件名------你不写文件名,浏览器帮你补默认首页;
  • 前端就是这样的:客户端的东西解析得太多了,帮我们进行一系列复杂的请求或者写入数据。

短连接

复制代码
浏览器 ── HTTP request ──→ 服务器
浏览器 ←── HTTP response ── 服务器
                             │
                          close(短连接)
浏览器拿到应答后进一步处理

一次 request + 一次 response,服务器就 close------这就是 HTTP 无连接特性的体现:每次请求都要建立新的连接。

七、依样画葫芦:写一个仿 HTTP 的自定义协议

请求和应答的轮廓都齐了,笔记里的原话:"依据这个就可以仿照这个写自定义协议了"------Response 报文和 request 报文都是不同的,就是字符串的格式不相同;请求行/状态行 + Kv 报头 + 空行 + 正文,四段式骨架照搬,内容自己定。手搓协议的功课,到这里就能照着 HTTP 抄作业了。

总结

  • URL = 协议 + 服务器地址(+端口 80) + 文件路径 + 查询字符串;HTTP 本质 = 全网唯一文件路径,网页就是文件;
  • URL 就是传参,特殊符号必须编码(空格 → %20)才不干扰解析;
  • HTTP 以行为单位、不依赖第三方库:发送者看是结构体序列化,接收者看是层次字符串;
  • 面向字节流 → 必须循环读到 \r\n 才算完整;空行是报头与正文的分界;
  • 请求行:方法(GET/POST) + URI + 版本;应答状态行:版本 + 状态码 + 描述,server 必须应答;
  • HTTP 请求本质 = 把服务器 Linux 特定目录的文件返回给客户端,默认补 index.html;一问一答即短连接。

下一篇换个视角往上爬:为什么需要协议、协议栈为什么叫"栈"、IP 和 MAC 各管什么------把网络分层再往下捅一层。

相关推荐
大侠归来1 小时前
深入理解 ioctl 系统调用:从原理到实战
网络
Zhang~Ling1 小时前
Linux网络:五种IO模型及其工作原理与应用
linux·网络·php
万联WANFLOW1 小时前
从工具协同到智能体驱动:Meta Muse 小型企业版的架构演进与行业启示
网络·架构·业界资讯
渡我白衣1 小时前
深入理解 Transformer:Decoder与Masked_Attention
linux·服务器·网络·c++·人工智能·深度学习·transformer
AKA__Zas2 小时前
TCP 与 IP 浅显皮毛
服务器·网络·tcp/ip
源流之道10 小时前
联想Y700 五代(TB323FU)刷 ColorOS 16 教程指南
网络·ai·刷机指南·刷机心得
优化Henry11 小时前
LTE 载波频率与频点配置详解
运维·网络·学习·5g·信息与通信
科力锐品牌君11 小时前
应用级灾备 | 海量非结构化数据如何实现高效数据保护
linux·运维·网络·安全·系统安全·数据安全·灾备
盛世宏博北京12 小时前
档案库房防护能力升级:从八防到十二防的物联网全维度感知防护体系建设方案
网络·物联网