Appearance
FTP、SMTP、POP3 等协议概览
概念
应用层的协议很多,但 408 只考两件事:它们各自用 TCP 还是 UDP、以及"谁主动推、谁被动拉"。 抓住这两条主线,这一章就是一张能背完的表。
★ 两条主线:
| 主线 | 分类 | 典型 |
|---|---|---|
| ① 传输层依赖 | TCP(要可靠、有会话) | FTP、SMTP、POP3、IMAP、HTTP、Telnet、SSH |
| UDP(要快、一问一答或自己管可靠性) | DNS(查询)、DHCP、TFTP、SNMP、RTP | |
| ② 数据流向 | 推 push(服务器主动送) | SMTP(发信方推给收信方) |
| 拉 pull(客户端主动取) | POP3、IMAP、HTTP、FTP(都是客户去取) |
★ 一句话说清本章的地位:前面 net/50-dns.md 与 net/51-http.md 讲透了两个最重要的应用层协议——本章把它们放进"协议家族"里横向对照,重点是把端口号、传输层、数据流向这三张表一次性记牢。
与上一章的衔接:上一章(net/51-http.md)说"HTTP 是请求-响应(拉)模式,用 TCP 80"——本章的 SMTP 恰恰是"推"模式的唯一代表,正好形成对照;而"SMTP 只传 7 位 ASCII"这条限制,也解释了为什么电子邮件需要 MIME 与 base64。
原理
一、熟知端口与传输层依赖(一张必背总表)
★ 端口号的三段划分:0 ~ 1023 熟知端口(由 IANA 统一分配,普通程序不能用);1024 ~ 49151 登记端口;49152 ~ 65535 临时端口(客户端发起连接时由系统临时分配,net/41-tcp.md 的锚点里 49152 就是这么来的)。
★ 应用层协议总表(必背,考场默写级):
| 协议 | 端口 | 传输层 | 用途 | 备注 |
|---|---|---|---|---|
| FTP 数据 | 20 | TCP | 传文件内容 | 只在传文件时建立 |
| FTP 控制 | 21 | TCP | 传命令 | 整个会话保持 |
| SSH | 22 | TCP | 安全远程登录 | 加密的 Telnet |
| Telnet | 23 | TCP | 远程登录 | 明文,已不推荐 |
| SMTP | 25 | TCP | 发送邮件 | 推模式 |
| DNS | 53 | UDP / TCP | 域名解析 | 超 512 B 或区域传送改 TCP |
| DHCP | 67(服务器)/ 68(客户端) | UDP | 动态分配 IP | 客户端还没有 IP,只能广播 |
| TFTP | 69 | UDP | 简单文件传输 | 小文件、引导用,自己实现重传 |
| HTTP | 80 | TCP | 万维网 | 明文 |
| POP3 | 110 | TCP | 收邮件(下载) | 拉模式 |
| IMAP | 143 | TCP | 收邮件(在线管理) | 拉模式 |
| SNMP | 161(代理)/ 162(陷阱) | UDP | 网络管理 | 报文简单、周期性轮询 |
| HTTPS | 443 | TCP | 万维网(加密) | HTTP + TLS |
⚠️ 三个最容易记错的:① TFTP 是 UDP 而不是 TCP("简单"就是"不做连接、自己做重传");② SNMP 也是 UDP(网络管理要轮询很多设备,用 TCP 的话每个设备都要建连,代价太大);③ DHCP 用的是两个端口号 67 与 68——服务器用 67、客户端用 68,不是同一个端口。
二、FTP:一个"用两条连接"的协议
★ FTP 的独特设计:命令与数据走不同的连接(这叫"带外控制",out-of-band control):
text
客户 服务器
│ │
│ ①控制连接: TCP, 服务器 21 号端口 │
├───────────────────────────────────────────►│ ★ 整个会话期间一直保持
│ 传: USER / PASS / CWD / RETR / STOR ... │ (只传命令, 不传数据)
│ │
│ ②数据连接: 每传一次文件建立一次 │
│◄───────────────────────────────────────────┤
│ 主动模式: 服务器用 20 号端口主动连客户 │
│ 被动模式: 客户主动连服务器的随机端口 │
│ ★ 传完这个文件就关闭, 下次传文件再建一条 │★ 为什么要分两条连接:
| 好处 | 说明 |
|---|---|
| 命令与数据互不干扰 | 传一个大文件时,仍能在控制连接上发"中止"命令 |
| 控制连接可以一直保持 | 一次登录后可以连续传很多文件,不必反复认证 |
| 数据连接可以按需选参数 | 每次传文件都能重新协商传输模式、类型 |
★ 主动模式与被动模式(防火墙时代的产物):
| 模式 | 谁发起数据连接 | 端口 | 问题 |
|---|---|---|---|
| 主动模式(PORT) | 服务器主动连客户端 | 服务器 20 → 客户端的随机端口 | 客户端在防火墙后时会连不进来 |
| 被动模式(PASV) | 客户端主动连服务器 | 客户端 → 服务器的随机端口 | 服务器要开放一大段端口 |
⚠️ FTP 的另一个特点:它把"文件"当作字节流原样搬,不做编码转换——这与 SMTP 恰好相反(SMTP 只能走 7 位 ASCII)。 这也是"传文件用 FTP、传邮件用 SMTP+base64"的根源。
三、电子邮件:SMTP 推、POP3/IMAP 拉
★ 三段路径(必背,箭头方向不能反):
text
用户代理 UA 发送方邮件服务器 接收方邮件服务器 用户代理 UA
(Outlook 等) (MTA) (MTA) (收件人)
│ │ │ │
│ ① SMTP (推) │ │ │
├─────────────────────►│ │ │
│ │ ② SMTP (推) │ │
│ ├─────────────────────────►│ ③ 收件人邮箱(存储) │
│ │ │ │
│ │ │ ④ POP3 / IMAP (拉) │
│ │ ├────────────────────►│
★ ① 与 ② 都是 SMTP (25 号端口), 都是"推"
★ ④ 是拉: POP3 (110) 把邮件下载到本地; IMAP (143) 在服务器上在线管理
★ 中间那两个"邮件服务器"常被称作 MTA (Mail Transfer Agent)★ 三个协议的角色对照(必背):
| 协议 | 端口 | 方向 | 干什么 | 特点 |
|---|---|---|---|---|
| SMTP | 25 | 推 | 把邮件从 UA 送到发送方服务器、再从发送方服务器送到接收方服务器 | 只能传 7 位 ASCII,所以需要 MIME 编码 |
| POP3 | 110 | 拉 | 把邮件从服务器下载到本地 | 默认下载后从服务器删除("下载即离线") |
| IMAP | 143 | 拉 | 在服务器上管理邮件 | 邮件留在服务器,多设备可同步 |
★ SMTP 只传 7 位 ASCII 带来的代价(算一笔账):
text
★ 二进制附件必须先编码成 7 位 ASCII 才能过 SMTP
-> MIME 规定用 base64
★ base64: 每 3 个字节 -> 4 个 ASCII 字符, 所以体积膨胀 4/3 倍
★ 算例: 1 MiB = 1048576 B 的附件
分组数 = (1048576 + 2) / 3 = 349526
编码后 = 349526 x 4 = 1398104 B (约 1.33 MiB)
★ 另外还要按行插入 CRLF (MIME 规定每行不超过 76 字符) -> 实际略大一点⚠️ "POP3 与 IMAP 的差别"是常考对比:POP3 是"下载即搬走"(默认从服务器删除,多设备不同步);IMAP 是"留在服务器上管理"(多设备看到同一份,可只取首部、可搜索)。 判据一句话:要不要在多个设备上看到同一份邮件——要就 IMAP。
四、DHCP:客户端还没有 IP,所以只能广播
★ DORA 四步(必背,顺序不能错):
text
客户端 (还没有 IP, 用 0.0.0.0, 端口 68) 服务器 (端口 67)
│ │
│ ① DHCP DISCOVER (广播: 谁是 DHCP 服务器?) │
├─────────────────────────────────────────────────►│
│ ② DHCP OFFER (广播/单播: 我这儿有个 192.168.1.100)
│◄─────────────────────────────────────────────────┤
│ ③ DHCP REQUEST (广播: 我要用 192.168.1.100) │ ★ 广播是为了
├─────────────────────────────────────────────────►│ 通知其他服务器
│ ④ DHCP ACK (确认, 同时下发掩码/网关/DNS) │
│◄─────────────────────────────────────────────────┤
★ 四步首字母 = D-O-R-A
★ 客户端连自己的 IP 都还没有 -> 只能用"广播"把请求发出去
★ 为什么第 3 步仍要广播: 可能有多个服务器都发了 OFFER,
广播 REQUEST 就是在"公开声明我选了哪一个", 其他服务器便可以撤回★ 租期与续租:DHCP 分配的是"租期"而不是永久地址——默认租期常为 86400 s(1 天);到达
★ DHCP 中继代理:DHCP 靠广播,而路由器默认不转发广播——所以跨网段时要在每个网段放一个"中继代理",把广播转成单播发给真正的 DHCP 服务器。
五、其余几个"露个脸"的协议
| 协议 | 端口 | 传输层 | 定位 | 一句话 |
|---|---|---|---|---|
| TFTP | 69 | UDP | 简单文件传输 | 无认证、无目录、只做小文件;靠"停等 + 重传"自己补可靠性 |
| SNMP | 161 / 162 | UDP | 网络管理 | 管理站周期性轮询代理(161);代理主动上报陷阱(162) |
| Telnet | 23 | TCP | 远程登录 | 明文传输,包括密码;已被 SSH 取代 |
| SSH | 22 | TCP | 安全远程登录 | 加密 + 认证,现代运维标配 |
| RTP | 动态 | UDP | 实时音视频 | 允许少量丢包,最怕延迟;由 RTCP 做质量反馈 |
★ 为什么这些"小协议"偏爱 UDP:
text
① 报文极小, 一问一答 -> 建连接的 1 个 RTT 占比太高 (DNS、SNMP、DHCP)
② 请求方自己就能处理丢包 -> 不需要 TCP 的重传机制 (TFTP 的停等重传)
③ ★ 启动阶段连 IP 都没有 -> 只能用广播, 而 TCP 无法广播 (DHCP)
④ 实时性优先 -> 宁可丢一帧也不要等重传 (RTP)
★ 反过来, 凡是"要传一整个文件/一整套会话、且不能出错"的, 都用 TCP
(FTP、SMTP、HTTP、SSH)示例
例 1:C 实现——端口表与查找
参数:13 条常用熟知端口;查找时用一个未登记的协议名演示返回值。
#include <stdio.h>
#include <string.h>
/* 熟知端口表: 名称 / 端口 / 传输层 */
static struct { const char *name; int port; const char *trans; } tab[] = {
{"FTP-data", 20, "TCP"}, {"FTP", 21, "TCP"},
{"SSH", 22, "TCP"}, {"Telnet", 23, "TCP"},
{"SMTP", 25, "TCP"}, {"DNS", 53, "UDP/TCP"},
{"DHCP", 67, "UDP"}, {"TFTP", 69, "UDP"},
{"HTTP", 80, "TCP"}, {"POP3", 110, "TCP"},
{"IMAP", 143, "TCP"}, {"SNMP", 161, "UDP"},
{"HTTPS", 443, "TCP"}
};
#define NTAB ((int)(sizeof(tab) / sizeof(tab[0])))
static int getport(const char *name) {
int i;
for (i = 0; i < NTAB; i++)
if (strcmp(tab[i].name, name) == 0) return tab[i].port;
return -1; /* -1 表示表里没有 */
}
int main(void) {
const char *ask[] = {"SMTP", "POP3", "TFTP", "GOPHER"};
int i;
printf("(1) 常用熟知端口\n");
printf(" %-9s %-5s %s\n", "proto", "port", "transport");
for (i = 0; i < NTAB; i++)
printf(" %-9s %-5d %s\n", tab[i].name, tab[i].port, tab[i].trans);
printf("\n");
printf("(2) 端口查找\n");
for (i = 0; i < 4; i++) {
int p = getport(ask[i]);
if (p < 0)
printf(" lookup(%-7s) -> -1 (未登记)\n", ask[i]);
else
printf(" lookup(%-7s) -> %d\n", ask[i], p);
}
printf("\n");
printf("(3) DHCP 的 DORA 四步 (客户端还没有 IP, 只能广播)\n");
{
const char *nm[] = {"DISCOVER", "OFFER", "REQUEST", "ACK"};
const char *src[] = {"client:68", "server:67", "client:68", "server:67"};
const char *dst[] = {"broadcast:67", "broadcast:68",
"broadcast:67", "broadcast:68"};
for (i = 0; i < 4; i++)
printf(" step%d %-9s %-12s -> %s\n", i + 1, nm[i], src[i], dst[i]);
}
printf(" ★ 共 4 个报文; 租期 86400 s -> T1 = 50%% = 43200 s, T2 = 87.5%% = 75600 s\n");
printf("\n");
printf("(4) 邮件路径 (先推后拉)\n");
printf(" UA --SMTP:25--> 发送方 MTA --SMTP:25--> 接收方 MTA --POP3:110/IMAP:143--> UA\n");
printf(" ★ SMTP 是推, POP3/IMAP 是拉\n");
printf(" ★ SMTP 只能传 7 位 ASCII -> MIME base64 膨胀 4/3 = 1.3333 倍\n");
printf(" ★ 1 MiB 二进制 -> base64 后 = %d x 4 = %d B (膨胀 %.2f 倍)\n",
(1048576 + 2) / 3, (1048576 + 2) / 3 * 4, 1398104 / 1048576.0);
printf("\n");
printf("(5) FTP 用两条连接\n");
printf(" 控制连接: 21 号端口, 整个会话保持, 传命令\n");
printf(" 数据连接: 20 号端口 (主动模式) 或随机端口 (被动模式)\n");
return 0;
}
c 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
预期输出:
text
(1) 常用熟知端口
proto port transport
FTP-data 20 TCP
FTP 21 TCP
SSH 22 TCP
Telnet 23 TCP
SMTP 25 TCP
DNS 53 UDP/TCP
DHCP 67 UDP
TFTP 69 UDP
HTTP 80 TCP
POP3 110 TCP
IMAP 143 TCP
SNMP 161 UDP
HTTPS 443 TCP
(2) 端口查找
lookup(SMTP ) -> 25
lookup(POP3 ) -> 110
lookup(TFTP ) -> 69
lookup(GOPHER ) -> -1 (未登记)
(3) DHCP 的 DORA 四步 (客户端还没有 IP, 只能广播)
step1 DISCOVER client:68 -> broadcast:67
step2 OFFER server:67 -> broadcast:68
step3 REQUEST client:68 -> broadcast:67
step4 ACK server:67 -> broadcast:68
★ 共 4 个报文; 租期 86400 s -> T1 = 50% = 43200 s, T2 = 87.5% = 75600 s
(4) 邮件路径 (先推后拉)
UA --SMTP:25--> 发送方 MTA --SMTP:25--> 接收方 MTA --POP3:110/IMAP:143--> UA
★ SMTP 是推, POP3/IMAP 是拉
★ SMTP 只能传 7 位 ASCII -> MIME base64 膨胀 4/3 = 1.3333 倍
★ 1 MiB 二进制 -> base64 后 = 349526 x 4 = 1398104 B (膨胀 1.33 倍)
(5) FTP 用两条连接
控制连接: 21 号端口, 整个会话保持, 传命令
数据连接: 20 号端口 (主动模式) 或随机端口 (被动模式)⚠️ 三点说明:
- 本机无 C 编译器:此段代码逐行人工审查,并用等价的 Python 实现实跑核对,输出逐字一致。
1398104这个数是"算出来"的:base64 把每 3 字节打成 4 个字符,1 MiB = 1048576 B 要分成 组,编码后 B——比值 ,正是那个著名的"膨胀三分之一"。 ((1048576 + 2) / 3就是"向上取整除以 3"的整数写法。)getport返回 表示"表里没有":这是一种很常见的 C 约定——端口号都是正数,用负数当"失败"标记,调用方必须先判负再用。 题目里若问"未登记的协议查表结果是什么",答"返回错误码(如 )而不是 0"——因为 0 是保留端口,不能用来表示失败。
例 2:Python——端口速查、DORA 时序与邮件流程
def pad(s, w):
"""按"显示宽度"补空格: 汉字算 2 列, 否则终端里对不齐"""
return s + ' ' * max(0, w - sum(2 if ord(c) > 0x2000 else 1 for c in s))
PORT = [('FTP-data', 20, 'TCP'), ('FTP', 21, 'TCP'), ('SSH', 22, 'TCP'),
('Telnet', 23, 'TCP'), ('SMTP', 25, 'TCP'), ('DNS', 53, 'UDP/TCP'),
('DHCP', 67, 'UDP'), ('TFTP', 69, 'UDP'), ('HTTP', 80, 'TCP'),
('POP3', 110, 'TCP'), ('IMAP', 143, 'TCP'), ('SNMP', 161, 'UDP'),
('HTTPS', 443, 'TCP')]
print('=== ① 传输层依赖归类 ===')
for proto, port, tr in PORT:
print(' ' + pad(proto, 10) + pad(str(port), 6) + pad(tr, 10)
+ ('可靠、有会话' if tr == 'TCP' else
('极简、一问一答' if tr == 'UDP' else '查询 UDP, 超长/区传送 TCP')))
print(' ★ 用 TCP: FTP / SSH / Telnet / SMTP / HTTP / POP3 / IMAP / HTTPS')
print(' ★ 用 UDP: DHCP / TFTP / SNMP / RTP, 以及 DNS 的查询')
print()
print('=== ② 推 (push) 还是拉 (pull) ===')
print(' ' + pad('模式', 10) + pad('协议', 26) + '谁主动')
for a, b, c in [('推 push', 'SMTP', '发送方服务器主动送给接收方'),
('拉 pull', 'POP3 / IMAP', '收件人主动去服务器取'),
('拉 pull', 'HTTP / HTTPS', '浏览器主动去服务器取'),
('拉 pull', 'FTP', '客户主动去服务器取文件')]:
print(' ' + pad(a, 10) + pad(b, 26) + c)
print(' ★ 应用层里"推"的典型只有 SMTP; 其余几乎都是拉')
print()
print('=== ③ DHCP 的 DORA 四步 ===')
print(' ' + pad('步', 6) + pad('报文', 12) + pad('源', 14) + pad('目的', 18) + '作用')
dora = [('①', 'DISCOVER', 'client:68', 'broadcast:67', '找 DHCP 服务器'),
('②', 'OFFER', 'server:67', 'broadcast:68', '提供一个可用地址'),
('③', 'REQUEST', 'client:68', 'broadcast:67', '公开声明"我要这个"'),
('④', 'ACK', 'server:67', 'broadcast:68', '确认并下发掩码/网关/DNS')]
for a, b, c, d, e in dora:
print(' ' + pad(a, 6) + pad(b, 12) + pad(c, 14) + pad(d, 18) + e)
lease = 86400
print(' ★ 租期 %d s -> T1 = 50%% = %d s 请求续租; T2 = 87.5%% = %d s 广播重试'
% (lease, lease * 50 // 100, int(lease * 87.5 / 100)))
print(' ★ 客户端还没有 IP, 所以四步都用广播; 路由器默认不转发广播 -> 需中继代理')
print()
print('=== ④ 电子邮件: 三段路径 ===')
path = [('①', 'UA -> 发送方 MTA', 'SMTP', '25', '推'),
('②', '发送方 MTA -> 接收方 MTA', 'SMTP', '25', '推'),
('③', '接收方 MTA -> UA', 'POP3 / IMAP', '110 / 143', '拉')]
print(' ' + pad('段', 6) + pad('路径', 30) + pad('协议', 14) + pad('端口', 12) + '方向')
for a, b, c, d, e in path:
print(' ' + pad(a, 6) + pad(b, 30) + pad(c, 14) + pad(d, 12) + e)
print(' ★ 两段都用 SMTP 推; 收件人那一段才是拉')
print()
print('=== ⑤ POP3 与 IMAP 的差别 ===')
print(' ' + pad('对比项', 20) + pad('POP3', 30) + 'IMAP')
for a, b, c in [('端口', '110', '143'),
('邮件存放位置', '下载到本地(默认从服务器删除)', '留在服务器上'),
('多设备同步', '不同步, 各下各的', '同步, 看到同一份'),
('按需取部分', '不支持, 整封下载', '支持只取首部/正文/附件'),
('判据', '只想在一台机器上看', '要在多设备上看同一份')]:
print(' ' + pad(a, 20) + pad(b, 30) + c)
print()
print('=== ⑥ SMTP 只能传 7 位 ASCII 的代价 ===')
size = 1048576
groups = (size + 2) // 3
print(' 原始二进制 1 MiB = %d B' % size)
print(' base64 分组 = ceil(%d / 3) = %d 组' % (size, groups))
print(' 编码后 = %d x 4 = %d B' % (groups, groups * 4))
print(' 膨胀比 = %d / %d = %.4f (理论值 4/3 = %.4f)' % (groups * 4, size, groups * 4 / size, 4 / 3))
print(' ★ 再加 MIME 行尾 CRLF (每行 <= 76 字符) -> 实际还要再大一点')
print()
print('=== ⑦ 为什么这些小协议偏爱 UDP ===')
for a, b in [('DNS 查询', '报文小、一问一答, 建连的 1 个 RTT 占比太高'),
('DHCP', '★ 启动时连 IP 都没有, 只能用广播, 而 TCP 不能广播'),
('TFTP', '请求方自己做停等重传, 不需要 TCP 的重传机制'),
('SNMP', '要轮询大量设备, 逐个建 TCP 连接代价太大'),
('RTP', '实时音视频宁可丢一帧, 也不要等重传带来的延迟')]:
print(' ' + pad(a, 12) + b)
print(' ★ 反过来: 要传整个文件或整套会话且不能出错的, 一律用 TCP')
print()
print('=== ⑧ FTP 的两条连接与两种模式 ===')
print(' ' + pad('连接/模式', 22) + pad('谁发起', 14) + pad('端口', 22) + '特点')
for a, b, c, d in [('控制连接', '客户端', '服务器 21', '整个会话保持, 只传命令'),
('数据连接 / 主动模式', '服务器', '服务器 20 -> 客户随机端口',
'客户在防火墙后会被拦'),
('数据连接 / 被动模式', '客户端', '客户 -> 服务器随机端口',
'服务器要开放一段端口')]:
print(' ' + pad(a, 22) + pad(b, 14) + pad(c, 22) + d)
print(' ★ "带外控制"的意义: 传大文件时仍能在控制连接上发"中止"命令')
python 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
输出对照(真实运行结果):
=== ① 传输层依赖归类 ===
FTP-data 20 TCP 可靠、有会话
FTP 21 TCP 可靠、有会话
SSH 22 TCP 可靠、有会话
Telnet 23 TCP 可靠、有会话
SMTP 25 TCP 可靠、有会话
DNS 53 UDP/TCP 查询 UDP, 超长/区传送 TCP
DHCP 67 UDP 极简、一问一答
TFTP 69 UDP 极简、一问一答
HTTP 80 TCP 可靠、有会话
POP3 110 TCP 可靠、有会话
IMAP 143 TCP 可靠、有会话
SNMP 161 UDP 极简、一问一答
HTTPS 443 TCP 可靠、有会话
★ 用 TCP: FTP / SSH / Telnet / SMTP / HTTP / POP3 / IMAP / HTTPS
★ 用 UDP: DHCP / TFTP / SNMP / RTP, 以及 DNS 的查询
=== ② 推 (push) 还是拉 (pull) ===
模式 协议 谁主动
推 push SMTP 发送方服务器主动送给接收方
拉 pull POP3 / IMAP 收件人主动去服务器取
拉 pull HTTP / HTTPS 浏览器主动去服务器取
拉 pull FTP 客户主动去服务器取文件
★ 应用层里"推"的典型只有 SMTP; 其余几乎都是拉
=== ③ DHCP 的 DORA 四步 ===
步 报文 源 目的 作用
① DISCOVER client:68 broadcast:67 找 DHCP 服务器
② OFFER server:67 broadcast:68 提供一个可用地址
③ REQUEST client:68 broadcast:67 公开声明"我要这个"
④ ACK server:67 broadcast:68 确认并下发掩码/网关/DNS
★ 租期 86400 s -> T1 = 50% = 43200 s 请求续租; T2 = 87.5% = 75600 s 广播重试
★ 客户端还没有 IP, 所以四步都用广播; 路由器默认不转发广播 -> 需中继代理
=== ④ 电子邮件: 三段路径 ===
段 路径 协议 端口 方向
① UA -> 发送方 MTA SMTP 25 推
② 发送方 MTA -> 接收方 MTA SMTP 25 推
③ 接收方 MTA -> UA POP3 / IMAP 110 / 143 拉
★ 两段都用 SMTP 推; 收件人那一段才是拉
=== ⑤ POP3 与 IMAP 的差别 ===
对比项 POP3 IMAP
端口 110 143
邮件存放位置 下载到本地(默认从服务器删除) 留在服务器上
多设备同步 不同步, 各下各的 同步, 看到同一份
按需取部分 不支持, 整封下载 支持只取首部/正文/附件
判据 只想在一台机器上看 要在多设备上看同一份
=== ⑥ SMTP 只能传 7 位 ASCII 的代价 ===
原始二进制 1 MiB = 1048576 B
base64 分组 = ceil(1048576 / 3) = 349526 组
编码后 = 349526 x 4 = 1398104 B
膨胀比 = 1398104 / 1048576 = 1.3333 (理论值 4/3 = 1.3333)
★ 再加 MIME 行尾 CRLF (每行 <= 76 字符) -> 实际还要再大一点
=== ⑦ 为什么这些小协议偏爱 UDP ===
DNS 查询 报文小、一问一答, 建连的 1 个 RTT 占比太高
DHCP ★ 启动时连 IP 都没有, 只能用广播, 而 TCP 不能广播
TFTP 请求方自己做停等重传, 不需要 TCP 的重传机制
SNMP 要轮询大量设备, 逐个建 TCP 连接代价太大
RTP 实时音视频宁可丢一帧, 也不要等重传带来的延迟
★ 反过来: 要传整个文件或整套会话且不能出错的, 一律用 TCP
=== ⑧ FTP 的两条连接与两种模式 ===
连接/模式 谁发起 端口 特点
控制连接 客户端 服务器 21 整个会话保持, 只传命令
数据连接 / 主动模式 服务器 服务器 20 -> 客户随机端口客户在防火墙后会被拦
数据连接 / 被动模式 客户端 客户 -> 服务器随机端口服务器要开放一段端口
★ "带外控制"的意义: 传大文件时仍能在控制连接上发"中止"命令五条结论:
- ★ 端口与传输层是一对一绑定的:FTP 20/21、SSH 22、Telnet 23、SMTP 25、HTTP 80、POP3 110、IMAP 143、HTTPS 443 走 TCP;DHCP 67/68、TFTP 69、SNMP 161/162 走 UDP;DNS 53 是"查询 UDP、超长与区域传送 TCP"的双面协议。
- ★ 应用层里"推"的典型只有 SMTP:收信(POP3/IMAP)与取网页(HTTP)、取文件(FTP)全是"拉"。
- ★ DHCP 的四步必须全广播:因为客户端连自己的 IP 都还没有;第 3 步
REQUEST仍广播,是为了让落选的其他服务器撤回它发出的OFFER。 - ★ POP3 与 IMAP 的判据是"要不要多设备同步":POP3 下载即删、各下各的;IMAP 留在服务器、多设备看到同一份。
- ★ SMTP 只传 7 位 ASCII,所以附件要 base64:1 MiB 膨胀成 1398104 B(比值约 1.3333)——这是"电子邮件比原始文件大三分之一"的由来。
考点
考点
1. 必背结论
- ★★ 端口表:FTP 20(数据)/ 21(控制)、SSH 22、Telnet 23、SMTP 25、DNS 53、DHCP 67(服务器)/ 68(客户端)、TFTP 69、HTTP 80、POP3 110、IMAP 143、SNMP 161(轮询)/ 162(陷阱)、HTTPS 443。
- ★★ 端口三段:0 ~ 1023 熟知端口 / 1024 ~ 49151 登记端口 / 49152 ~ 65535 临时端口。
- ★★ 用 UDP 的:DHCP、TFTP、SNMP、RTP,以及 DNS 的查询;其余(FTP、SSH、Telnet、SMTP、HTTP、POP3、IMAP、HTTPS)用 TCP。
- ★★ FTP 用两条连接:控制连接(21,整个会话保持,只传命令)与数据连接(20 或随机端口,每传一个文件建一次)——这叫带外控制。
- ★ FTP 主动模式:服务器用 20 号端口主动连客户端;被动模式:客户端主动连服务器的随机端口。
- ★★ 邮件三段路径:UA →(SMTP 25)→ 发送方 MTA →(SMTP 25)→ 接收方 MTA →(POP3 110 / IMAP 143)→ UA。
- ★★ SMTP 是推、POP3/IMAP 是拉。
- ★★ SMTP 只能传 7 位 ASCII:二进制附件必须 base64 编码,体积膨胀 4/3 倍(1 MiB → 349526 × 4 = 1398104 B)。
- ★ POP3 与 IMAP 的判据:要不要多设备同步——要就 IMAP。
- ★★ DHCP 的 DORA 四步:DISCOVER → OFFER → REQUEST → ACK;四步都用广播(客户端还没有 IP)。
- ★ DHCP 用 UDP 的 67(服务器)与 68(客户端)两个端口。
- ★ DHCP 租期:
租期时向原服务器请求续租; 时向所有服务器广播重试。 - ★ DHCP 中继代理:路由器默认不转发广播,跨网段必须靠中继把广播转成单播。
- ★ TFTP 用 UDP 69:无认证、只做小文件,靠"停等 + 重传"自己补可靠性。
- ★ SNMP 用 UDP 161/162:管理站轮询代理用 161,代理主动上报陷阱用 162。
- ★ Telnet 23 是明文(含密码);SSH 22 加密,已取代 Telnet。
- ★ 应用层"推"的典型只有 SMTP。
2. 高频陷阱
- 把 FTP 的数据端口记成 21:错。控制连接是 21、数据连接是 20——两者都算 FTP,所以题目问"FTP 用哪个端口"时要分清问的是哪条连接。
- 认为"FTP 只用一条连接":错。它是"命令与数据分开走"的经典设计(带外控制)。
- 把 TFTP 归到 TCP:错。TFTP 用 UDP 69("简单"就是"不建连接、自己做重传")。
- 把 SNMP 归到 TCP:错。SNMP 用 UDP 161/162。
- 把 DHCP 的端口写成同一个:错。服务器 67、客户端 68。
- 认为"DHCP 的四步只有前两步是广播":错。DORA 四步都要广播——第 3 步
REQUEST广播是为了让落选的服务器撤回OFFER。 - 把 SMTP 与 POP3 的方向搞反:错。SMTP 是推(发信),POP3/IMAP 是拉(收信)。
- 认为"邮件全程都用 SMTP":错。只有"送信到服务器、服务器到服务器"这两段用 SMTP;收件人取信用 POP3/IMAP。
- 把 POP3 与 IMAP 的端口搞反:POP3 = 110、IMAP = 143。
- 认为"POP3 与 IMAP 只是端口不同":错。核心差别是"邮件留在服务器还是下载即删"——直接决定多设备能否同步。
- 忘记 SMTP 的"7 位 ASCII"限制:错。没有这条限制就解释不了 MIME 与 base64 的存在。
- 把 base64 膨胀算成 2 倍:错。是 4/3 倍(约 1.33)——因为 3 字节变成 4 个字符。
- 认为"DHCP 分配的是永久地址":错。分配的是"租期",到期要续租。
- 把 SSH 与 Telnet 的端口搞反:SSH 22、Telnet 23(22 在前,且 22 更安全)。
- 认为"HTTPS 是新协议所以有新端口 8443":错。默认 443(8443 只是常见的代理/备用端口,不是标准默认值)。
3. 解题模板("应用层协议归属题")
① 看到协议名 -> 先想"端口 + 传输层"两件事:
FTP 20/21 TCP | SSH 22 TCP | Telnet 23 TCP | SMTP 25 TCP
DNS 53 UDP(查询)/TCP(超长) | DHCP 67/68 UDP | TFTP 69 UDP
HTTP 80 TCP | POP3 110 TCP | IMAP 143 TCP | SNMP 161/162 UDP
HTTPS 443 TCP
② 看到"方向"问题 -> 只记一条:
推 = SMTP; 拉 = POP3 / IMAP / HTTP / FTP
③ 看到邮件题 -> 画三段:
UA --SMTP--> 发送方MTA --SMTP--> 接收方MTA --POP3/IMAP--> UA
④ 看到 DHCP 题 -> 背 DORA:
DISCOVER -> OFFER -> REQUEST -> ACK, 四步广播
★ 客户端无 IP 是"为什么广播"的唯一理由
⑤ 看到"为什么用 UDP" -> 从四条里挑:
报文小(RTT 占比高) / 请求方自己管重传 / 没有 IP 只能广播 / 实时性优先
⑥ 看到"传输/编码开销" -> base64 = 4/3:
编码后 = ceil(原始字节 / 3) x 44. 与相邻章节的接口
net/51-http.md(HTTP/HTTPS):HTTP 是"拉"模式的标准代表;本章的 SMTP 是"推"模式的唯一典型——这一组对照是应用层最爱考的对比题。net/50-dns.md(DNS):SMTP 发信前必须先查 MX 记录;DHCP 会把 DNS 服务器地址一并下发给客户端——三个协议串起来才是一次"完整上网"。net/40-udp.md与net/41-tcp.md:本章的"用 TCP 还是 UDP"就是这两章的选型应用——要可靠性与会话的选 TCP,要"一问一答 + 省一个 RTT"的选 UDP。net/42-handshake.md(连接管理):"建连要 1 个 RTT"正是小协议偏爱 UDP 的理由;FTP 的两条连接意味着两次三次握手。soft/31-crypto.md(密码学基础):base64 是"编码"不是"加密"——它不提供任何机密性,只解决"7 位 ASCII 通道里怎么过二进制"的问题;这一点与 TLS 的加密完全不同。os/30-filesystem.md与os/32-io.md:POP3 的"下载并删除"与 IMAP 的"留在服务器"在操作系统层面就是"本地文件"与"远程文件系统"的差别;邮件客户端本地缓存目录正是 IMAP 保留首部的结果。
小结
- ★★ 传输层归属:FTP / SSH / Telnet / SMTP / HTTP / POP3 / IMAP / HTTPS 走 TCP;DHCP / TFTP / SNMP 走 UDP;DNS 查询用 UDP、超长与区域传送改 TCP。
- ★★ FTP 两条连接:21 控制连接(全程保持)+ 20 数据连接(每传一个文件建一次);主动模式服务器连客户、被动模式客户连服务器。
- ★★ 邮件三段路径:UA →(SMTP 25)→ 发送方 MTA →(SMTP 25)→ 接收方 MTA →(POP3 110 / IMAP 143)→ UA;SMTP 推、POP3/IMAP 拉。
- ★★ SMTP 只能传 7 位 ASCII:附件 base64 膨胀 4/3(1 MiB → 1398104 B)。
- ★ POP3 下载即删(不同步);IMAP 留在服务器(可多设备同步)。
- ★★ DHCP 四步 DORA:全广播,因为客户端还没有 IP;租期 T1 = 50%、T2 = 87.5% 续租;跨网段需中继代理。
- ★ TFTP 69 / SNMP 161 走 UDP;Telnet 23 明文、SSH 22 加密。
- ★ 应用层"推"的只有 SMTP,其余都是拉。
上一篇:HTTP 与 HTTPS | 本门已收满:回到 网络 · 计算机网络
评论(0)
当前浏览器不允许本地存储,评论无法保存。
还没有评论,来说两句。