AR-26710-头像

Linux Day29——HTTP与网络排障

---

title: Linux:HTTP 与网络排障(应用层与端口约定、curl、请求与响应骨架、状态码、端口开≠服务好、ping 与 ICMP、traceroute、四步排查)

date: 2026-10-28

description:TCP 之上由应用层协议约定内容格式、80/443 只是约定不是证明;curl 发请求、-I 只要响应头、-v 看全过程;HTTP 请求四段与请求行三块;响应状态行与状态码首位分类;LISTEN 只说明内核在等连接;ping 用 ICMP Echo 探主机、ttl 是剩余跳数;ping 不通不等于不可达;traceroute 靠 TTL 递增逼每跳报名字、星号是不回话;网络排查四步:名字→机器→端口→应用

tags: [Linux, 网络基础, HTTP, curl, ICMP, ping, traceroute, 排障]

---

 

# Linux:HTTP 与网络排障(块 4 第 6 天)

 

> 📌 GitHub:https://github.com/AR-firefly

 

## 笔记区

 

### 点 1:应用层与端口约定

 

**场景**:三次握手把 TCP 连接建好了,但这条管子只保证字节一个不少、按顺序送到,不管里面装的是什么。

 

**应用层管"内容怎么组织"**:四层从上往下是应用层 → 传输层 → 网络层 → 链路层。传输层(TCP)保证可靠送达、不解释内容;内容长什么样由应用层协议规定。

 

**HTTP**(HyperText Transfer Protocol,超文本传输协议):规定一套"问"和"答"的格式,两边照这个格式才能互相看懂。

 

> **英文原句**:HTTP messages are the mechanism used to exchange data between a server and a client in the HTTP protocol.

> **中文翻译**:HTTP 消息是 HTTP 协议中服务器与客户端之间交换数据所使用的手段。

> **说人话**:HTTP 规定了一套"问"和"答"的格式,两边照着这个格式才能互相看懂。

 

**端口是约定,不是证明**:

 

- 同一台机器可以同时跑网页、DNS、SSH 等服务,一个 TCP 连接交给谁靠**端口号**

- 80 习惯给 HTTP,443 习惯给 HTTPS——这是大家事先谈好的门牌

- 谁能监听哪个端口不受限制,端口开着也不能反推里面一定是什么协议

 

**`ss` 输出怎么读**(10-24 学过,这天重新用):

 

- `Local Address:Port` 那栏按冒号切开:前面是绑定地址,后面是端口

- 不加 `-n` 时 `ss` 会做名字反解,把 53 显示成 `domain`

- `domain` 是 53 端口的服务名,写在 `/etc/services` 这张"端口号 ↔ 服务名"对照表里

 

**实测**:`ss -lta` 看到三行 `domain`,加 `-n` 后变成 `53`。「-n 就是别翻译,把数字列出来」;「不加 -n 的优势:一看就看出来哪个是 DNS 服务」。

 

**记法**:`-l` = listen(监听)、`-t` = TCP、`-n` = numeric(数字,不反解)。

 

### 点 2:`curl` 与 HTTP 请求骨架

 

**场景**:在浏览器地址栏打下网址回车,电脑最先发出去的不是网页,而是一段按格式写好的文字。

 

**`curl`**:命令行工具,名字来自 client URL,作用是发一个 HTTP 请求、把服务器回的东西打印出来,不渲染页面。

 

- `-v`(verbose):把请求和响应的全过程打出来

- `-I`(--head):只发 HEAD、只取响应头

 

> **英文原句**:`-I, --head` — Fetch the headers only. HTTP-servers feature the command `HEAD` which this uses to get nothing but the header of a document.

> **中文翻译**:`-I, --head` —— 只获取头部。HTTP 服务器提供 `HEAD` 命令,curl 用它只取文档的头部,不取其余内容。

> **说人话**:加 `-I`,curl 就只问"这个资源的头信息",服务器只回头部,不传网页正文。

 

**HTTP 请求由四段组成**:

 

1. **请求行**:如 `GET / HTTP/2`

2. **头部**:一行一个 `键: 值`

3. **空行**:标记头部结束

4. **体**:正文;`GET` 请求没有体

 

**请求行内部再分三块**:方法 + 路径 + 版本。`GET /index.html HTTP/1.1` = 取(方法)+ 首页文件(路径)+ 用 1.1 版说话(版本)。

 

> **英文原句**:The start-line in HTTP/1.x requests (POST /users HTTP/1.1 in the example above) is called a "request-line" and is made of three parts:

> **中文翻译**:HTTP/1.x 请求里的起始行(上面例子中的 `POST /users HTTP/1.1`)称为"请求行",由三部分组成。

> **说人话**:请求消息的第一行,格式是"方法 路径 版本",三块用空格隔开。

 

**用户实测**:`curl -v https://example.com -o /dev/null` 的输出里,`>` 开头是发出去的请求,`<` 开头是服务器回的响应。请求行 `GET / HTTP/2`,头部三行 `Host` / `User-Agent` / `Accept`,随后一个单独的 `>` 就是空行。

 

**`-o /dev/null`**:把响应正文丢进黑洞(`/dev/null`),避免网页内容刷屏盖住过程。

 

### 点 3:HTTP 响应与状态码

 

**场景**:请求发出去之后,服务器回来的那一半长什么样。

 

**响应也分四段**:状态行 → 头部 → 空行 → 体。

 

> **英文原句**:The start-line (HTTP/1.1 201 Created above) is called a "status line" in responses, and has three parts:

> **中文翻译**:起始行(上例中的 `HTTP/1.1 201 Created`)在响应里称为"状态行",由三部分组成。

> **说人话**:服务器回的第一行,告诉你"这次结果怎么样"。

 

**状态码第一位决定类别**:

 

- `2xx` 成功(200 OK)

- `3xx` 转向:资源搬家了,新地址写在 `Location:` 头里

- `4xx` 客户端错:请求本身有问题(404 找不到路径)

- `5xx` 服务器错

 

「2 通,3 换地方,4 用户问题,5 对面问题」。

 

**`301` 的细节**:`curl -I` 不会自动跟过去,只把 301 给你看;要跟得加 `-L`(follow location)。

 

**`404` 与 `NXDOMAIN` 的区别**(易混):

 

- `404`:名字找到了、服务器连上了、它回话了,只是那个路径下没资源 → **能说明服务器是好的**

- `NXDOMAIN`:DNS 账本里这个名字根本没登记 → 连服务器都没找到,推不出服务器死活

 

**实测**:`curl -I https://example.com` 回 `HTTP/2 200`;`curl -I http://gitlab.com` 回 `HTTP/1.1 301 Moved Permanently`,带 `Location: https://gitlab.com/`;`curl -I https://example.com/no-such-page-xyz` 回 `HTTP/2 404`。

 

### 点 4:端口开 ≠ 服务好

 

**场景**:本机 53 端口明明在监听,`nc -vz 127.0.0.53 53` 也说连上了,但 `curl -I http://127.0.0.53:53` 拿不到任何东西。

 

**把"通"拆成三层**:

 

1. **端口在监听**:内核在这个门牌号上等连接(`ss -ltn` 看到的就是这层)

2. **TCP 握手成功**:敲门有人应(`nc -vz` 试的是这层)

3. **应用层能对话**:对方听得懂并回一条 HTTP 响应(`curl` 要的是这层)

 

**每一层成功,推不出下一层也成功。**

 

**`nc`**(netcat):网络里的小刀,既能当客户端连端口、也能监听,还能传文件。`nc -vz 地址 端口`:`-v` 说结果,`-z` 只探端口不发数据,默认走 TCP。

 

**实测**:

 

- `nc -vz 127.0.0.53 53` → `succeeded!`

- `curl -I http://127.0.0.53:53` → `curl: (52) Empty reply from server`

 

**`Empty reply from server`**:连上了,但服务器一个字没回就把连接关了。53 端口后面坐的是 DNS 服务,收到 HTTP 文本不认识,直接关掉。

 

**「端口坐着的是 DNS,不认识 HTTP 文本,不管你」。

 

**curl 的退出码**(不是 HTTP 状态码):`0` 正常、`52` 空回复、`28` 超时。查法 `man 1 curl` 的 `EXIT CODES` 段。

 

### 点 5:`ping` 与 ICMP

 

**场景**:不确定一台机器死活,最土的办法就是喊一嗓子。

 

**`ping` 的机制**:

 

> **英文原句**:ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to elicit an ICMP ECHO_RESPONSE from a host or gateway.

> **中文翻译**:ping 使用 ICMP 协议中必备的 ECHO_REQUEST 数据报,来引出目标主机或网关返回一个 ICMP ECHO_RESPONSE。

> **说人话**:ping 发一个"在吗",对方正常的话回一个"在"。

 

**ICMP**(Internet Control Message Protocol,网际控制报文协议):网络层的邮差,只送通知、不运数据。`ping` 和 `traceroute` 都靠它。

 

**输出怎么读**:

 

- `icmp_seq=1`:第几个包

- `ttl=50`:IP 层的 TTL,回包到手里还剩多少跳

- `time=253 ms`:这个包往返用了多久

- 最后统计:丢包率 + `rtt min/avg/max/mdev`(最小 / 平均 / 最大 / 波动)

 

**`-c` 与 `-i`**:

 

- `-c 4`:count,只发 4 个就停(不加会一直发)

- `-i 0.2`:interval,包间隔改成 0.2 秒(默认 1 秒)

 

**`time=3001ms` 不是平均往返**:整轮四包、间隔默认 1 秒,3 个间隔就是 3 秒,所以总耗时约 3000ms。平均往返看 `rtt` 那行的 avg。

 

**实测**:`ping -c 4 1.1.1.1` 默认间隔,`time=3001ms`、`rtt avg 252.769ms`;改成 `-i 0.2` 后 `time=606ms`,验证了 3 秒是等待间隔堆出来的。

 

**`ttl` 与 DNS 的 TTL 同名不同物**:

 

- IP 的 `ttl`:包还能被转发几次,每过一台路由器减 1,减到 0 就丢弃

- DNS 的 TTL:一条记录能在缓存里放多久

 

`ping` 用的是 ICMP

 

### 点 6:ping 不通 ≠ 不可达

 

**场景**:本机 `ping` 网关 100% 丢包,`ping 1.1.1.1` 却 0% 丢包。

 

**原因**:ICMP Echo 是"喊一声,对方愿意才回"。很多网关、防火墙、云服务器的策略是 ICMP 一律不回——它照样转发包,只是不搭理 ping。

 

**因此**:

 

- ping 通 → 基本说明这层路走到了

- ping 不通 → **什么也证明不了**

 

**要交叉验证**:

 

- `ip neigh`:邻居表里有没有它的 MAC,说明这一段网络上它确实存在

- `ip route get 目标`:系统打算从哪块网卡、经哪个网关发出去

- `nc -vz 地址 端口`:TCP 能连上,说明它活得好好的

 

**实测**:

 

- `ping -c 3 172.17.144.1` → 100% packet loss

- `ping -c 3 1.1.1.1` → 0% packet loss

- `ip neigh` → `172.17.144.1 dev eth0 lladdr 00:15:5d:8e:be:b3 REACHABLE`

- `ip route get 1.1.1.1` → `via 172.17.144.1 dev eth0 src 172.17.158.107`

- 结论:网关是好的,它必须帮包出外网,只是不回 ICMP

 

### 点 7:`traceroute` 怎么走

 

**场景**:`ping` 只知道"到不了",不知道卡在哪一段。

 

**它是干嘛的**:trace(追踪)+ route(路线),画出包从本机到目标,中间一站一站经过哪些路由器——网络版的快递轨迹。

 

> **英文原句**:traceroute tracks the route packets taken from an IP network on their way to a given host. It utilizes the IP protocol's time to live (TTL) field and attempts to elicit an ICMP TIME_EXCEEDED response from each gateway along the path to the host.

> **中文翻译**:traceroute 追踪数据包从 IP 网络前往某台主机的途中走过的路线。它利用 IP 协议的 TTL(存活时间)字段,尝试从沿途每台网关引出一次 ICMP TIME_EXCEEDED 响应。

> **说人话**:它一路让包"故意过期",骗路上的路由器逐个出来报个名字。

 

**为什么必须故意让包过期**:路由器转包时是沉默的,不会主动报告自己。只有当包在它手上 TTL 减到 0,它必须扔掉,扔的时候必须回一句 ICMP "Time Exceeded",这句话里带着它自己的地址。

 

> **英文原句**:We start our probes with a ttl of one and increase by one until we get an ICMP "port unreachable" (or TCP reset), which means we got to the "host", or hit a max (which defaults to 30 hops). Three probes (by default) are sent at each ttl setting and a line is printed showing the ttl, address of the gateway and round trip time of each probe.

> **中文翻译**:探测从 TTL=1 开始,每次加 1,直到收到 ICMP"端口不可达"(或 TCP reset)——表示到达目标主机,或达到上限(默认 30 跳)。每个 TTL 默认发三个探测包,打印一行,显示 TTL、网关地址和每个探测的往返时间。

> **说人话**:第一个包只准活一站,第一台路由器就得说"包死在这儿";第二个包活两站……一站一站问出来。

 

**参数**:`-n` 不反解名字、`-m 5` 最多 5 跳。

 

**`* * *` 的含义**:这一跳的三个探测包都没回来——对方不回话。**不代表包没经过**:路线是排好队一站接一站的,后面还有地址出现,就证明包从它那儿过去了。

 

**实测**:`traceroute -n -m 8 8.8.8.8` 的输出:第 1 跳 `172.17.144.1`(本机网关)、第 2 跳 `10.32.0.1`、第 3 跳 `10.50.255.253`、第 4 跳 `* * *`、第 5 跳 `221.226.71.193`、第 6 跳 `* * *`、第 7、8 跳有地址但夹着星号。

 

### 点 8:网络排查四步

 

**顺序**:名字 → 机器 → 端口 → 应用。每步一个命令,哪步失败就停在那。

 

| 步 | 问什么 | 命令 |

| --- | ------------ | ----------------------------------- |

| 1 | 名字有地址吗 | `getent hosts 名字` |

| 2 | 整台机器通吗 | `ping -c 3 名字` |

| 3 | 端口通吗 | `nc -vz -w 3 名字 端口` |

| 4 | 应用会说话吗 | `curl -I --max-time 5 https://名字` |

 

**每一步成功都排除掉下面一层**:名字解析成功说明 DNS 没事;ping 通说明路由和邻居没事(`ip neigh` / `ip route get` 就可以跳过);端口通说明服务在听;curl 有响应说明应用正常。

 

**口诀**:有地址、到得了、门开着、会说人话。

 

## 线索区(学完后合上材料,自问自答)

 

**Q: 80 和 443 是什么?它们不能证明什么?**

A: 是约定俗成的门牌(HTTP / HTTPS);不能证明端口里一定跑着那种服务。

 

**Q: `curl` 的 `-I` 和 `-v` 各看什么?**

A: `-I`(head)只要响应头;`-v`(verbose)把请求和响应全过程都打出来。

 

**Q: HTTP 请求由哪四段组成?请求行内部又分哪三块?**

A: 请求行 / 头部 / 空行 / 体;请求行 = 方法 + 路径 + 版本。

 

**Q: 状态码首位 2/3/4/5 各代表哪一方的责任?**

A: 2 成功、3 重定向、4 客户端错、5 服务器错。

 

**Q: `ss` 看到 LISTEN,能不能说明服务能用?为什么?**

A: 不能;LISTEN 只说明内核在等连接,不保证对方说你要的协议(53 端口会回 `Empty reply`)。

 

**Q: `ping` 用什么协议?`ttl` 和 `time` 各是什么?**

A: ICMP;`ttl` 是剩余跳数,`time` 是单个包往返时间。

 

**Q: ping 网关全丢包但外网正常,网关坏了吗?凭什么判断?**

A: 没坏;`ip neigh` 显示 REACHABLE,且外网包必须经它转发。

 

**Q: `traceroute` 里的 `* * *` 是没有经过那台机器吗?**

A: 不是;那是对方不回话,路线固定,后面还有地址就说明经过了。

 

**Q: 网络排查的四步顺序和对应命令?**

A: `getent hosts` → `ping -c 3` → `nc -vz -w 3` → `curl -I`。

 

---

 

## 总结(50字以内,用自己的话概括今天学到了什么)

 

网络问题从底往上问:名字有地址、机器到得了、端口门开着、应用会说人话;端口开着和 ping 不通都只是单点信号,证明不了整条链。

 

---

 

## 复习卡片

 

| 概念 | 必学/了解 | 一句话 | 场景 |

| --------------------------------------- | --------- | ------------------------------------------------------ | ----------------- |

| HTTP | 必学 | 浏览器与服务器之间的问答格式 | 看网页请求 |

| `curl` / `-I` | 必学 | 命令行发 HTTP 请求;`-I` 只要响应头 | 抓一次响应 |

| 起始行 / 头部 / 空行 / 体 | 必学 | 消息四段:第一行说结果,头部是标签,空行分界,体是内容 | 读请求与响应 |

| 状态码 | 必学 | 第一位定类别:2 通、3 走、4 请求方错、5 服务器错 | 判断责任方 |

| ICMP | 必学 | 网络层的邮差,只送通知不运数据 | ping / traceroute |

| `ping` | 必学 | 发 Echo Request 收 Echo Reply;`-c` 次数、`-i` 间隔 | 探主机死活 |

| `traceroute` | 必学 | 逐跳追踪路线;`-n` 不反解、`-m` 最大跳数 | 查断在哪一段 |

| TTL(IP 版) | 必学 | 剩余跳数,每过一台路由器减 1;和 DNS 的 TTL 无关 | 读 ping 输出 |

| 应用层 | 必学 | 规定内容怎么组织,不管可靠送达 | 理解分层 |

| 端口号 | 必学 | 一台机器区分多个服务的门牌,是约定不是证明 | 读 `ss` 输出 |

| 请求行 | 必学 | 方法 + 路径 + 版本 | 读请求 |

| 状态行 | 必学 | 版本 + 状态码 + 原因短语 | 读响应 |

| `nc`(netcat) | 必学 | `-z` 只探端口不发数据,默认 TCP | 测端口通不通 |

| `ip neigh` | 必学 | 邻居表,看同段网络里有没有它的 MAC | 验证主机存在 |

| `ip route get` | 必学 | 问"去某目标走哪条路" | 验证出口 |

| `Empty reply from server` | 了解 | 连上了但对方一个字不回就关连接(curl 退出码 52) | 排障读报错 |

| `301` 与 `Location` | 了解 | 3xx 指路,新地址在 `Location` 头;`curl -L` 才会跟 | 抓响应头 |

| `-v` / `Host` / `User-Agent` / `Accept` | 了解 | 不记,`curl --help` / `man 1 curl` 能查 | 看请求细节 |

 

---

 

## 流程附加段

 

### 旧知识回收

 

| 概念 | 一句话 | 出处 |

| ----------------------------------- | ------------------------------------------------------ | ------------------------------------------------ |

| `start` / `stop` / `restart` 的对象 | 动作落在指定的 unit 上,不是 systemd 管理器本身 | 复习抽考第 1 问答错(说成"控制 systemd 管理器") |

| `stop` 与 `disable` | `stop` 停进程;`disable` 只删 `.wants/` 里的符号链接 | 复习抽考第 1 问重考 |

| `enable` 与 `is-enabled` | `enable` 建符号链接、不启动;`is-enabled` 看链接在不在 | 复习抽考第 2 问 |

| `daemon-reload` | 让 systemd 重读磁盘上的 unit 文件,换上内存里的旧定义 | 复习抽考第 3 问 |

| `-c` 与 `-C` | ping 的选项分大小写,`-c` 是次数 | 点 5 练时打成大写 C |

| `ttl` 两个含义 | IP 的 = 剩余跳数;DNS 的 = 缓存时长 | 点 5 考时混了 |

 

### 收尾自测

 

8 个点各问一题:

 

1. 80/443 约定什么、不能证明什么 —— 对

2. `-I`/`-v` 各看什么、请求四段 —— 前半对;四段与请求行三块讲清后答对

3. 状态码首位分类 —— 对

4. `LISTEN` 能否证明服务能用 —— 答"能",用 53 端口的 `Empty reply` 撞破后答对

5. `ping` 用什么协议 —— 答"TCP",讲 ICMP 后答对

6. 网关 ping 全丢但外网通 —— 结论对,理由补讲后能说出

7. `* * *` 是否表示没经过 —— 对

8. 四步排查顺序 —— 对

 

### 今日产出验收

 

| 产出项(来源 `S1块4开周清单.md:70`) | 证据 | 判定 |

| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ---- |

| 讲清"端口开 ≠ 服务好" | 实测 53 端口 LISTEN、`nc` 成功、`curl` 回 `Empty reply`;口头说出"DNS 不认识 HTTP 文本" | ✅ |

| 用 ping / traceroute 做一次连通性判断 | 用户跑出 `ping` 网关 100% 丢包 + 外网 0%,用 `ip neigh`/`ip route get` 判断网关完好;跑出 `traceroute -n -m 8 8.8.8.8` 并读出每条的含义 | ✅ |

 

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2503_94114317/article/details/169913249

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--