第6章 计算机网络

第6章 计算机网络

计算机网络是 CSP-S 初赛重点(概念辨析、IP/子网计算、协议归属),复赛中虽不直接考,但理解网络分层有助于看懂题目背景(如"给定一个网络拓扑求最短路""按 IP 分组"类建模题)。本章把每个可计算的知识点都写成 C++17 示例,方便亲手验证。


6.1 网络拓扑结构与分类

6.1.1 按覆盖范围分类

类型范围典型
PAN个人周边(数米)蓝牙
LAN局域网(一栋楼/园区)校园网、机房
MAN城域网(城市)城市政务网
WAN广域网(跨国家/洲)互联网骨干

6.1.2 按拓扑分类

总线型、星型、环型、树型、网状型。星型(中心交换机)最常见;网状型可靠性最高、成本高,用于骨干网。

6.1.3 按交换方式

电路交换(如传统电话,独占链路)、报文交换、分组交换(互联网主流,数据切包独立传输)。


6.2 OSI 七层模型与 TCP/IP 四层模型

6.2.1 OSI 七层(从下到上)

层名称功能典型设备/协议
1物理层比特传输、电压、接口集线器、双绞线
2数据链路层帧、MAC、差错控制交换机、以太网
3网络层路由、IP 寻址路由器、IP、ICMP
4传输层端到端可靠/不可靠传输TCP、UDP
5会话层会话管理—
6表示层加密、压缩、编码—
7应用层用户应用HTTP、DNS、FTP

记忆口诀(从下到上):物数网传会表应。

6.2.2 TCP/IP 四层(从下到上)

网络接口层 → 网际层(IP)→ 传输层(TCP/UDP)→ 应用层(HTTP/DNS 等)。

关系:TCP/IP 把 OSI 的"会话/表示/应用"合并为应用层,"物理/数据链路"合并为网络接口层。

6.2.3 协议封装(教学示例)

数据从应用层往下传时,每层加上自己的头部(有的加尾部),称为封装。下面用字符串模拟"逐层加头":

#include <iostream>
#include <string>
using namespace std;

int main() {
string data = "Hello";
// 应用层 -> 传输层(加端口头) -> 网络层(加IP头) -> 链路层(加MAC头)
string seg = "[TCP头:端口]" + data;
string pkt = "[IP头:地址]" + seg;
string frame = "[MAC头]" + pkt + "[MAC尾]";
cout << "最终在线路上传输的帧: " << frame << "\n";
return 0;
}

6.3 数据链路层

6.3.1 MAC 地址

MAC 地址是网卡硬件地址,48 位(6 字节),全球唯一,形如 00:1B:44:11:3A:9D。前 24 位为厂商标识(OUI),后 24 位为设备编号。工作在数据链路层,用于同一局域网内寻址。

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;

// 把 48 位 MAC 整数格式化为 xx:xx:xx:xx:xx:xx
string macToStr(unsigned long long mac) {
char buf[18];
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
(int)((mac >> 40) & 0xFF), (int)((mac >> 32) & 0xFF),
(int)((mac >> 24) & 0xFF), (int)((mac >> 16) & 0xFF),
(int)((mac >> 8) & 0xFF), (int)(mac & 0xFF));
return buf;
}

int main() {
unsigned long long mac = 0x001B44113A9Dull;
cout << "MAC 地址: " << macToStr(mac) << "\n"; // 00:1B:44:11:3A:9D
return 0;
}

6.3.2 以太网与交换机

  • 以太网是最主流的 LAN 技术,帧格式含目的/源 MAC、类型、数据、CRC。
  • 交换机工作在数据链路层,根据 MAC 表转发帧(比集线器智能,集线器是物理层广播)。
  • 冲突域/广播域:交换机每个端口一个冲突域;VLAN 可分割广播域。

6.4 网络层(IP、子网划分)

6.4.1 IPv4 地址与分类(初赛常考)

IPv4 地址 32 位,点分十进制 a.b.c.d(每节 0~255)。早期分类编址(现已由 CIDR 取代,但初赛仍考):

类别首字节范围网络/主机位用途
A1~1268/24超大型网络(0 和 127 保留)
B128~19116/16中型网络
C192~22324/8小型网络
D224~239—组播
E240~255—保留
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;

// 按首字节判断 IPv4 类别
string ipClass(const string& s) {
int a; sscanf(s.c_str(), "%d.", &a);
if (a >= 1 && a <= 126) return "A";
if (a >= 128 && a <= 191) return "B";
if (a >= 192 && a <= 223) return "C";
if (a >= 224 && a <= 239) return "D(组播)";
if (a >= 240 && a <= 255) return "E(保留)";
return "特殊(0/127)";
}

int main() {
cout << "10.0.0.1 -> " << ipClass("10.0.0.1") << "\n"; // A
cout << "172.16.0.1 -> " << ipClass("172.16.0.1") << "\n"; // B
cout << "192.168.1.1 -> " << ipClass("192.168.1.1") << "\n"; // C
return 0;
}

6.4.2 CIDR 与子网掩码(初赛核心计算)

CIDR 用"IP/前缀长度"表示,如 192.168.1.100/24。前缀长度 p 表示子网掩码前 p 位为 1。

  • 子网掩码 = 前 p 个 1 后接 (32-p) 个 0。
  • 网络地址 = IP & 掩码(该子网最小地址)。
  • 广播地址 = 网络地址 | ~掩码(该子网最大地址)。
  • 可用主机数 = 2^(32-p) − 2(去掉网络地址和广播地址;p≥31 时特殊)。
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;

unsigned int ipToInt(const string& s) {
int a, b, c, d; sscanf(s.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d);
return ((unsigned int)a << 24) | ((unsigned int)b << 16) |
((unsigned int)c << 8) | (unsigned int)d;
}
string intToIp(unsigned int v) {
char buf[20];
sprintf(buf, "%u.%u.%u.%u", (v >> 24) & 0xFF, (v >> 16) & 0xFF,
(v >> 8) & 0xFF, v & 0xFF);
return buf;
}
unsigned int prefixToMask(int p) {
return (p == 0) ? 0u : (0xFFFFFFFFu << (32 - p));
}

int main() {
string ip = "192.168.1.100";
int p = 24;
unsigned int ipv = ipToInt(ip);
unsigned int mask = prefixToMask(p);
unsigned int net = ipv & mask;
unsigned int bcast = net | ~mask;
unsigned int hosts = (1u << (32 - p)) - 2;

cout << "IP: " << intToIp(ipv) << "\n";
cout << "掩码: " << intToIp(mask) << " (/ " << p << ")\n";
cout << "网络地址: " << intToIp(net) << "\n"; // 192.168.1.0
cout << "广播地址: " << intToIp(bcast)<< "\n"; // 192.168.1.255
cout << "可用主机数:" << hosts << "\n"; // 254
return 0;
}

初赛考法:给"主机数需求"反推前缀长度。例如要容纳 200 台主机,需 2^(32-p) − 2 ≥ 200 → 2^(32-p) ≥ 202 → 取 2⁸=256,故 32-p=8,p=24。

6.4.3 子网划分与路由

  • 子网划分:把大网络按借位拆成多个小子网(如 /24 借 2 位成 4 个 /26)。
  • 路由:路由器根据路由表转发 IP 包;ARP 把 IP 解析为 MAC(同一网段内);ICMP 用于网络诊断(ping、traceroute)。

6.5 传输层(TCP 与 UDP)

6.5.1 TCP vs UDP

特性TCPUDP
连接面向连接无连接
可靠性可靠(确认、重传、排序)不可靠(尽力交付)
速度较慢快
适用网页、文件、邮件视频、语音、DNS、游戏

6.5.2 TCP 三次握手与四次挥手

  • 三次握手(建立连接):客户端 SYN → 服务端 SYN+ACK → 客户端 ACK。
  • 四次挥手(释放连接):主动方 FIN → 被动方 ACK → 被动方 FIN → 主动方 ACK(因 TCP 全双工,关闭需双向各一次)。

三次握手时序图

TCP 三次握手时序图

四次挥手时序图

TCP 四次挥手时序图

6.5.3 流量控制与拥塞控制

  • 流量控制:用滑动窗口让发送方不超过接收方缓冲区(避免接收方来不及)。
  • 拥塞控制:慢启动、拥塞避免、快重传、快恢复,防止网络被压垮。

6.5.4 端口号(教学示例)

端口号 16 位(0~65535),用于区分同一主机上的不同应用:

区间名称示例
0~1023知名/系统端口HTTP 80、HTTPS 443、DNS 53、FTP 21、SSH 22
1024~49151注册端口用户程序注册
49152~65535动态/私有端口客户端临时端口
#include <iostream>
#include <string>
using namespace std;

string portType(int p) {
if (p <= 1023) return "知名/系统端口";
if (p <= 49151) return "注册端口";
return "动态/私有端口";
}

int main() {
cout << "端口 80 -> " << portType(80) << "\n"; // 知名
cout << "端口 8080 -> " << portType(8080) << "\n"; // 注册
cout << "端口 50000-> " << portType(50000)<< "\n"; // 动态
return 0;
}

6.5.5 应用层协议端口速查

协议端口传输层用途
HTTP80TCP网页
HTTPS443TCP加密网页
DNS53UDP(大包用TCP)域名解析
FTP21(控制)/20(数据)TCP文件传输
SSH22TCP安全远程登录
SMTP25TCP发邮件
POP3110TCP收邮件
TELNET23TCP远程登录(明文,已淘汰)

6.6 应用层协议简介

  • HTTP/HTTPS:超文本传输。HTTPS = HTTP + TLS 加密。请求方法 GET/POST;状态码 200 成功、404 未找到、500 服务器错误。
  • DNS:把域名解析成 IP。递归查询(问本地 DNS)与迭代查询(本地 DNS 逐层问根/顶级/权威)。
  • FTP:文件传输,需建立控制连接与数据连接。
  • SMTP/POP3/IMAP:邮件发送与接收。
#include <iostream>
#include <string>
using namespace std;

// 教学:拼接一个 HTTP/1.1 GET 请求字符串(不实际发包)
string buildGet(const string& host, const string& path) {
return "GET " + path + " HTTP/1.1\r\n"
+ "Host: " + host + "\r\n"
+ "Connection: close\r\n\r\n";
}

int main() {
cout << buildGet("www.example.com", "/index.html");
return 0;
}

说明:上面仅展示 HTTP 请求文本的拼法,真实发送需要 socket 编程,且涉及 TCP 连接建立(见 6.5.2),不在本章示例范围。


6.7 本章小结

  • 分层:OSI 七层(物数网传会表应),TCP/IP 四层(网接/网际/传输/应用)。
  • 数据链路层:MAC 48 位、交换机按 MAC 转发。
  • 网络层:IPv4 32 位、分类编址(A/B/C/D/E)、CIDR 子网划分(网络地址 = IP & 掩码、广播 = 网络 | ~掩码、主机数 = 2^(32-p) − 2)、ARP/ICMP。
  • 传输层:TCP 可靠(三次握手/四次挥手/滑动窗口)、UDP 快;端口 16 位分三档。
  • 应用层:HTTP 80、HTTPS 443、DNS 53、FTP 21、SSH 22 等端口务必记熟。

随堂检测(CSP-S 风格)

  1. (单选)OSI 模型中,IP 协议工作在第( )层

    • A. 物理层
    • B. 数据链路层
    • C. 网络层
    • D. 传输层
    参考答案

    C. 网络层。

    解析(考点):IP、ICMP、路由属于网络层(第3层);MAC/交换机属数据链路层,TCP/UDP 属传输层。

  2. (单选)IP 地址 192.168.1.100/24 所在子网的广播地址是( )

    • A. 192.168.1.0
    • B. 192.168.1.100
    • C. 192.168.1.255
    • D. 192.168.0.255
    参考答案

    C. 192.168.1.255。

    解析(考点):/24 掩码 255.255.255.0,网络地址 192.168.1.0,广播地址 = 网络 | ~掩码 = 192.168.1.255。

  3. (单选)下列端口号中,属于"知名端口"的是( )

    • A. 8080
    • B. 53
    • C. 50000
    • D. 49152
    参考答案

    B. 53。

    解析(考点):知名端口 0~1023,DNS 用 53;8080 属注册端口,50000/49152 属动态端口。

  4. (单选)TCP 建立连接需要( )

    • A. 两次握手
    • B. 三次握手
    • C. 四次握手
    • D. 不需要握手
    参考答案

    B. 三次握手。

    解析(考点):TCP 面向连接,建立用三次握手(SYN → SYN+ACK → ACK);释放才用四次挥手。

  5. (多选)下列说法中正确的有( )

    • A. UDP 比 TCP 更快但不可靠
    • B. 交换机工作在网络层
    • C. HTTPS = HTTP + TLS 加密
    • D. MAC 地址长度为 48 位
    参考答案

    A、C、D。

    解析(考点):交换机工作在数据链路层(B 错);UDP 无连接更快不可靠(A 对);HTTPS 即加密 HTTP(C 对);MAC 为 48 位(D 对)。

  6. (单选)某子网前缀长度为 /26,则该子网可用主机数为( )

    • A. 64
    • B. 62
    • C. 256
    • D. 254
    参考答案

    B. 62。

    解析(考点):可用主机数 = 2^(32-26) − 2 = 2⁶ − 2 = 64 − 2 = 62。

SShowball OI知识手册