计算机网络简明入门

大多数网络讨论都是一堆缩略语。忘掉配置细节吧——其中的核心洞见是什么?

  • 网络关乎通信
  • 文本是最简单的通信方式
  • 协议(Protocol)是读写文本的标准

在细节之下,网络其实就是一场 IM(即时通讯)对话。下面是我希望有人在我学习计算机如何通信时告诉我的内容。

TCP:文本层

传输控制协议(Transmission Control Protocol,TCP)提供了一个方便的假象:我们可以“直接”在两台计算机之间发送文本。TCP 依赖于 更底层 并且可以发送二进制数据,但暂时忽略这一点:

  • TCP 让我们能在计算机之间即时通信(Instant Message)

我们用 Telnet 来 IM,它是网络界的“记事本”:telnet 使用 TCP 发送和接收纯文本。它是一个没有广告和陌生好友请求的聊天客户端,清净自在。

让我们用 telnet (或 putty,一个更好的工具):

telnet google.com 80
[connecting...]
Hello Mr. Google!

我们连接到 google.com 的 80 端口(Web 请求的默认端口),并发送消息“你好,Google 先生!”。我们按了几次回车,等待回复:

<html>
...
<h1>Bad Request</h1>
Your client has issued a malformed or illegal request
...
</html>

格式错误?非法? 强大的 Google 不高兴了。它没理解我们,并返回了 HTML 说明了这一点。

但是,我们进行了一次对话:文本发过去,文本返回来。换句话说: 

 

协议(Protocol):要填写的表单

非结构化的聊天太随意了——服务器怎么知道我们想要做什么?我们需要一个 协议 (标准的通信方式)才能说得清楚。

我们一直都在使用协议

  • 把“收件人”和“发件人”地址写在信封上的特定位置
  • 填写银行表单(账号、存款金额等写在特定位置)
  • 说“Roger”或“10-4”表示无线电请求已被理解

协议让通信变得清晰。

案例研究:HTTP 协议(Protocol)

我们在每个 url 中都能看到 HTTP: http://google.com/。这是什么意思?

  • 连接到服务器 google.com(使用 TCP,默认端口 80)
  • 请求资源“/”(默认资源)
  • 使用超文本传输协议格式化请求

HTTP 是请求资源时要填写的“表单”。使用 HTTP 格式,上述请求看起来像这样:

GET / HTTP/1.0

记住, 它只是文本!我们正通过一次 IM 会话,用如下格式请求一个文件:[命令] [资源] [协议名/版本]。

这个命令被“IM”给了服务器(你的浏览器会附加额外信息,这是后话)。Google 的服务器返回了如下响应:

HTTP/1.0 200 OK
Cache-Control: private, max-age=0
Date: Sun, 15 Mar 2009 03:13:39 GMT
Expires: -1
Content-Type: text/html; charset=ISO-8859-1
Set-Cookie: PREF=ID=5cc6…
Server: gws
Connection: Close

<html>
(Google web page, search box, and cute logo)
</html>

哎呀。底部是供浏览器显示的 HTML。但顶部的那些乱七八糟的是什么?

嗯,假设我们只是拿到了要显示的原始 HTML。但如果有错误呢:服务器崩溃了、文件不存在,或者 google 就是不喜欢我们?

有些 元数据 (关于数据的数据)很有用。当我们在 Amazon 订一本书时 我们期望有一张装箱单 描述了订单:预期的收件人、价格、退货信息等。你不会想要一本光秃秃的书直接扔在门口。

协议也是类似的:接收方想知道一切是否正常。这里我们看到了臭名昭著的状态码,比如 404(资源未找到)或 200(一切正常)。这些头部不是真正的数据——它们是服务器附带的装箱单。

来自协议(Protocol)的洞见

研究现有的、流行的系统是理解工程决策的好方法。这里有几个例子:

二进制 vs 纯文本

二进制数据 二进制比文本更高效,但更难调试和生成(你知道怎么用几个十六进制编辑器?)。底层协议作为互联网的主干,使用二进制数据来维持性能。应用层协议(HTTP 及以上)使用文本数据以便于互操作。你不会就字节序问题和 HTTP 发生宗教战争。

有状态 vs. 无状态

有些协议是有状态的,这意味着服务器会记住与客户端的对话。例如,使用 SMTP 时,客户端打开连接并一次发出一个命令(比如向邮件添加收件人),然后关闭连接。有状态通信在具有多个步骤或条件的交易中非常有用。

无状态通信更简单:你将整个交易作为一次请求发送。每条“即时消息”独立存在,不需要其他消息。HTTP 是无状态的:你可以请求网页而无需向服务器介绍自己。

可扩展性

我们无法事先想到所有事情。我们如何为旧协议扩展新用户?

HTTP 有一个简单而有效的“头部”结构:一种看起来像“Header:Value”的元数据前缀。

如果你不认识发送过来的头部(新客户端,旧服务器),就忽略它。如果你期望某个头部但没看到(旧客户端,新服务器),就使用默认值。这就像在调查中加入一个“还有什么要告诉我们的吗?”部分。

纠错与可靠性

像 TCP 这样的底层协议的工作是确保数据可靠传输。但高层协议(如 HTTP)需要确保它是 正确 数据。错误如何处理和传达?客户端可以直接重试,还是服务器需要重置状态?

HTTP 自带一组错误码来处理各种情况。

可用性

网络化的妙处在于它在一台计算机上也能工作。Memcached 是一个很棒的缓存数据服务。你猜怎么着?它使用普通的旧文本命令(通过 TCP)来保存和检索数据。

你不需要复杂的 COM 对象或 DLL——你启动一个 Memcached 服务器,输入文本,输出文本。它是语言中立且易于访问的,因为任何像样的操作系统都支持网络。你甚至可以用 telnet 连入 Memcached 来调试它。

无线路由器类似:它们有一个可通过 HTTP 访问的控制面板。没有“路由器配置程序”——你只需用浏览器连接它。路由器提供网页,当你提交数据时,它会进行必要的配置更改。

像 HTTP 这样流行的协议你可以 假设 用户有一个客户端。

分层协议

协议可以分层。我们可能写一份简历,它是更大申请的一部分,而申请被塞进信封里。每个片段有自己的格式,对其他片段毫不知情。你的信封不关心简历——它只想要收件人和发件人地址写正确。

许多协议依赖 HTTP,因为它使用如此广泛(而不是像 Memcached 那样从零开始,它需要效率)。HTTP 有定义明确的方法来定义资源(URL)和命令(GET 和 POST),所以为什么不利用它们呢?

Web 服务正是这样做的。SOAP 协议将 XML 塞进 HTTP 命令中。REST 协议拥抱 HTTP,并尽可能使用现有的动词。

记住:这一切都是人为约定的

网络涉及 人类约定。因为纯文本无处不在且易于使用,它是大多数协议的基础。而 TCP 是交换文本最简单、支持最广泛的方式。

记住一切都是纯文本的 IM 对话 帮我理解那些不可避免的网络问题。有时候你需要深入 HTTP 才能弄明白 压缩缓存.

不要只死记细节;要把协议(Protocol)看作解决通信问题的策略。祝你网络愉快。

本系列其他文章

  1. 数制(Number Systems)与进制(Bases)
  2. GUID 快速指南
  3. 理解 Quake 的快速平方根倒数(Fast Inverse Square Root)算法
  4. 计算机网络简明入门
  5. 使用异或(XOR)交换两个变量
  6. 理解大端(Big Endian)与小端(Little Endian)字节序
  7. Unicode 与你
  8. 关于二进制文件格式的一点小曲
  9. 排序算法(Sorting Algorithms)

加入 45 万月度读者

喜欢这篇文章?还有更多内容能帮你建立持久、直观的数学理解。加入通讯以获取额外内容和最新更新。