网络与HTTP:让我们以数据包的形式踏上旅程

📖 6min read

本地主机和平,幻想破灭

当我在学校时,我的整个世界都是localhost。即使我安装了 XAMPP 之类的东西并使用 PHP 创建了一个公告板,这也是一个只在我的计算机上运行的世界。

刚进公司的时候,我有幸主要负责前端维护。这是一个基于Quasar(Vue.js)的管理页面,任务难度不高。我所要做的就是纠正拼写错误或调用我的前辈已经用axios.get()创建好的API并将其显示在屏幕上。

当时,axios 对我来说就像一根魔杖。尽管我不知道复杂的原理,但我只是输入网址,很快就检索到了数据。 我也有一个厚脸皮的想法,“前端和后端之间的通信没有什么特别的吧?”

但是和平并没有持续多久。因为我是一家中小型公司的‘活生生的全栈’开发者,人手紧缺。

很快,我必须为新功能创建自己的 API,而不是修改屏幕的时刻到来了。我使用 Spring Boot 启动了一个服务器,这是我从 YouTube 上很快学到的,并从前端发送了一个请求。然而,我的屏幕上出现的只是红色的CORS错误和Timeout错误,而不是数据。

“当我将它作为局部变量传递时,它工作得很好,但为什么我不能只使用网络?”

在我的计算机(本地主机)上将变量 A 移动到变量 B 是一种 100% 保证安全的方法。但局域网电缆之外的世界是不同的。这就像一个红绿灯坏了的十字路口,而我的数据是一辆卡车在那条危险的道路上行驶。一直以来,我只是在装车并发送,但我不知道卡车走了什么路线,也不知道它是如何划分的。

当您的数据离开计算机时,它就必须走上崎岖、狂野的道路。

数字物流中心配送系统

让我们拓展“数字物流中心”的世界观。现在我们要把工厂(计算机)生产的物品(数据)传送给远方的客户(服务器)。

1.包装:标准运输箱

无论我们要发送多大的数据(例如1GB的视频),都无法一次发送完毕。这是因为道路狭窄,卡车又小。因此,我们将数据切成非常小的块,并将它们放入标准化的盒子中。这是一个“数据包”。

2. IP(互联网协议):地址和导航

如果我只有一个盒子怎么办?您需要知道要去哪里。

3. TCP/UDP:传送方式的差异

现在我们需要决定将箱子发送到哪辆卡车。

应该确定(TCP)还是快速抛出(UDP)?

【代码验证】HTTP的真面目只是文本

我们常用的HTTP实际上只是运输卡车上承载的“信件内容”,称为TCP。让我们以最原始的方式(Socket)与Naver服务器对话,无需浏览器或库。您将看到 HTTP 是多么简单,只是一段文本。

import socket

# 1. 建立 TCP socket(拿起電話)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2. 連線到 Naver 伺服器(223.130.195.200)的 80 埠(撥號)
# 實際 Naver IP 可能變動(可用 nslookup [www.naver.com](https://www.naver.com) 確認)
target_host = "[www.naver.com](https://www.naver.com)"
target_port = 80
sock.connect((target_host, target_port))

# 3. 撰寫 HTTP 請求訊息(寫下要說的話)
# 最原始的 HTTP 請求形式
request = "GET / HTTP/1.1rnHost: [www.naver.com](https://www.naver.com)rnrn"

# 4. 傳送(說話)
sock.send(request.encode())

# 5. 接收回應(聆聽)
response = sock.recv(4096)
print(response.decode())

# 6. 關閉連線(掛斷)
sock.close()

执行结果(部分):

HTTP/1.1 200 OK
Server: NWS
Date: Mon, 01 Jan 2024 00:00:00 GMT
Content-Type: text/html; charset=UTF-8
...
<html>...</html>

分析:这就是当我们调用 axios.get() 时内部发生的所有事情。

HTTP 并不是一项特殊的技术,它只是“当我们通信时使用此协议(protocol)交换文本”的承诺

实践中的权衡:可靠性或速度

在实践中,尤其是后端开发,有时您必须在 TCP 和 UDP 之间做出选择。 (当然,大多数使用基于TCP的HTTP)

最近面试问题中经常被问到的

HTTP/3就是这种权衡的产物。我们使用的互联网(HTTP/1.1、HTTP/2)一直在TCP上运行。因为数据永远不应该被破坏。

但时代已经变了。人们希望不间断地观看 4K 视频。 TCP 一丝不苟的验证过程(握手)和“排队(Head of Line Blocking)”等功能现在已经变得令人沮丧。

谷歌是这么想的。 “嘿,我们就用UDP吧。我们可以解决应用程序层面的不安。快速发送很重要!”

这是QUIC协议,是HTTP/3的基础。放弃无条件稳定(TCP)而选择压倒性的速度(UDP),即使这意味着承担一些风险,也是现代技术的趋势。

为了获得更快的速度,我们甚至正在改变最低级别的传输(TCP -> UDP)。

结束语:想象一条看不见的路

现在我们知道数据是如何分解的(数据包)以及它通过什么卡车(TCP/UDP)传输。

当 API 请求在前端失败时,不要只是想“服务器死了吗?”像以前一样。 “哦,是不是3次握手失败了?是不是中间被路由器丢包了?还是DNS没找到地址?”如果你能想象一个这样的网络层,你就不再“只是一个编码员”

现在,我厂的货物已安全到达客户手中。但客户如何收到该商品、拆开包装并将其显示在屏幕上呢?我们发送的HTML代码将如何在浏览器中显示?

下次我们来聊聊Web开发的最终归宿,浏览器渲染的原理。

發佈留言