第3天:OSI七层模型
“网络协议就像流水线,每一层都有自己的分工。”
📚 今日目标
- 理解什么是OSI七层模型
- 掌握每一层的作用
- 理解数据封装和解封装过程
- 编写程序演示协议分层
🎯 为什么要分层?
生活中的例子:快递系统
想象你要给上海的朋友寄一本书:
你写信 ────────────────────────────> 朋友读信
↓ ↑
包装快递 ──────────────────────────> 拆开快递
↓ ↑
分拣中心 ──────────────────────────> 分拣中心
↓ ↑
运输车辆 ──────────────────────────> 运输车辆
每一层只关心自己的工作:
- 你只需要写信,不管怎么运输
- 快递员只负责包装,不管写的什么
- 司机只负责开车,不管包裹里是什么
这就是分层的思想!
分层的好处
- 降低复杂度:每层只处理自己的任务
- 标准化接口:层与层之间有明确的接口
- 易于维护:修改某一层不影响其他层
- 可替换:可以更换某一层的实现
📊 OSI七层模型
OSI(Open Systems Interconnection)是国际标准化组织(ISO)制定的网络模型。
七层概览
┌─────────────┬────────────┬──────────────┬──────────────┐
│ 层次 │ 名称 │ 作用 │ 例子 │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第7层 │ 应用层 │ 为用户提供 │ HTTP、FTP │
│ │Application │ 网络服务 │ SMTP、DNS │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第6层 │ 表示层 │ 数据格式转换│ 加密、压缩 │
│ │Presentation│ 编码、加密 │ JPEG、MPEG │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第5层 │ 会话层 │ 建立、管理 │ RPC、SQL │
│ │Session │ 会话 │ │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第4层 │ 传输层 │ 端到端通信 │ TCP、UDP │
│ │Transport │ 可靠传输 │ │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第3层 │ 网络层 │ 路由选择 │ IP、ICMP │
│ │Network │ 寻址 │ │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第2层 │ 数据链路层│ 帧传输 │ Ethernet │
│ │Data Link │ 错误检测 │ WiFi、PPP │
├─────────────┼────────────┼──────────────┼──────────────┤
│ 第1层 │ 物理层 │ 比特传输 │ 网线、光纤 │
│ │Physical │ 电信号 │ 无线电波 │
└─────────────┴────────────┴──────────────┴──────────────┘
记忆口诀
从上到下:
- 应(应用层)
- 表(表示层)
- 会(会话层)
- 传(传输层)
- 网(网络层)
- 数(数据链路层)
- 物(物理层)
英文口诀:All People Seem To Need Data Processing
🔍 各层详解
第7层:应用层(Application Layer)
作用:为应用程序提供网络服务
通俗理解:你直接使用的软件层面
例子:
- 浏览器打开网页(HTTP/HTTPS)
- 收发邮件(SMTP/POP3)
- 下载文件(FTP)
- 域名解析(DNS)
类比:快递公司的客服窗口
第6层:表示层(Presentation Layer)
作用:数据格式转换、加密、压缩
通俗理解:翻译官
例子:
- JPEG图片格式
- MP3音频格式
- 加密算法(SSL/TLS)
- 字符编码(UTF-8)
类比:快递包装、封装
第5层:会话层(Session Layer)
作用:建立、管理、终止会话
通俗理解:负责通话的接线员
例子:
- 登录会话
- 数据库连接
- RPC远程调用
类比:快递单号管理系统
第4层:传输层(Transport Layer)
作用:端到端的可靠传输
通俗理解:确保包裹完整送达
例子:
- TCP:可靠传输,确保数据不丢失
- UDP:快速传输,不保证可靠
关键概念:端口号(区分不同的应用)
类比:快递公司的分发系统
第3层:网络层(Network Layer)
作用:路由选择和寻址
通俗理解:找到最佳路径
例子:
- IP协议(IP地址)
- 路由器工作在这一层
关键概念:IP地址(定位设备位置)
类比:快递运输路线规划
第2层:数据链路层(Data Link Layer)
作用:帧传输,相邻节点之间的数据传输
通俗理解:同一条街道内的传送
例子:
- 以太网(Ethernet)
- WiFi
- MAC地址
关键概念:MAC地址(网卡的物理地址)
类比:同城快递站点之间的传递
第1层:物理层(Physical Layer)
作用:在物理媒介上传输比特流
通俗理解:实际的传输介质
例子:
- 网线(双绞线)
- 光纤
- 无线电波
关键概念:电信号、光信号、无线信号
类比:快递车、飞机、轮船
📦 数据封装过程
当你发送数据时,数据会经过封装过程:
应用层: [用户数据]
↓ 添加应用层头部
表示层: [表示层头部|用户数据]
↓ 添加会话层头部
会话层: [会话层头部|表示层头部|用户数据]
↓ 添加传输层头部
传输层: [TCP头部|数据] ← 称为"段"(Segment)
↓ 添加网络层头部
网络层: [IP头部|TCP头部|数据] ← 称为"包"(Packet)
↓ 添加数据链路层头部和尾部
数据链路层:[帧头|IP头部|TCP头部|数据|帧尾] ← 称为"帧"(Frame)
↓ 转换为比特流
物理层: 01010101010101... ← 比特流(Bits)
类比理解
你写的信 → 应用层数据
装进信封 → 传输层添加端口信息
写上地址 → 网络层添加IP地址
放入包裹箱 → 数据链路层添加MAC地址
快递车运输 → 物理层传输
🔧 实战项目:协议分层演示
让我们编写一个程序,模拟OSI七层模型的数据封装过程!
代码实现
# day03_osi_demo.py
# 功能:演示OSI七层模型的数据封装和解封装过程
class OSILayer:
"""OSI模型的基础层类"""
def __init__(self, name, layer_num):
self.name = name
self.layer_num = layer_num
def encapsulate(self, data):
"""封装数据:添加本层头部"""
header = f"[{self.name}头部]"
return header + data
def decapsulate(self, data):
"""解封装数据:移除本层头部"""
header = f"[{self.name}头部]"
if data.startswith(header):
return data[len(header):]
return data
class PhysicalLayer(OSILayer):
"""物理层:第1层"""
def __init__(self):
super().__init__("物理层", 1)
def encapsulate(self, data):
"""将数据转换为比特流"""
bits = ''.join(format(ord(c), '08b') for c in data)
print(f"📡 {self.name}: 将数据转换为比特流")
print(f" 比特流(前64位): {bits[:64]}...")
return bits
def decapsulate(self, bits):
"""将比特流转换为数据"""
chars = []
for i in range(0, len(bits), 8):
byte = bits[i:i+8]
if len(byte) == 8:
chars.append(chr(int(byte, 2)))
data = ''.join(chars)
print(f"📡 {self.name}: 将比特流转换为数据")
return data
class DataLinkLayer(OSILayer):
"""数据链路层:第2层"""
def __init__(self):
super().__init__("数据链路层", 2)
def encapsulate(self, data):
"""添加MAC地址(帧头和帧尾)"""
mac_src = "AA:BB:CC:DD:EE:FF" # 源MAC地址
mac_dst = "11:22:33:44:55:66" # 目标MAC地址
frame = f"[帧头|源MAC:{mac_src}|目标MAC:{mac_dst}]{data}[帧尾|CRC校验]"
print(f"🔗 {self.name}: 添加MAC地址")
print(f" 源MAC: {mac_src}")
print(f" 目标MAC: {mac_dst}")
return frame
def decapsulate(self, frame):
"""移除MAC地址"""
# 简化处理:移除帧头和帧尾
start = frame.find("]") + 1
end = frame.rfind("[")
data = frame[start:end]
print(f"🔗 {self.name}: 移除MAC地址")
return data
class NetworkLayer(OSILayer):
"""网络层:第3层"""
def __init__(self):
super().__init__("网络层", 3)
def encapsulate(self, data):
"""添加IP地址"""
ip_src = "192.168.1.100" # 源IP地址
ip_dst = "93.184.216.34" # 目标IP地址(example.com)
packet = f"[IP头|源IP:{ip_src}|目标IP:{ip_dst}|TTL:64]{data}"
print(f"🌐 {self.name}: 添加IP地址")
print(f" 源IP: {ip_src}")
print(f" 目标IP: {ip_dst}")
return packet
def decapsulate(self, packet):
"""移除IP头部"""
start = packet.find("]") + 1
print(f"🌐 {self.name}: 移除IP头部")
return start and packet[start:] or packet
class TransportLayer(OSILayer):
"""传输层:第4层"""
def __init__(self):
super().__init__("传输层", 4)
def encapsulate(self, data):
"""添加端口号(TCP头部)"""
port_src = 54321 # 源端口
port_dst = 80 # 目标端口(HTTP)
segment = f"[TCP头|源端口:{port_src}|目标端口:{port_dst}|序号:12345]{data}"
print(f"🚚 {self.name}: 添加端口号(TCP协议)")
print(f" 源端口: {port_src}")
print(f" 目标端口: {port_dst} (HTTP)")
return segment
def decapsulate(self, segment):
"""移除TCP头部"""
start = segment.find("]") + 1
print(f"🚚 {self.name}: 移除TCP头部")
return segment[start:]
class SessionLayer(OSILayer):
"""会话层:第5层"""
def __init__(self):
super().__init__("会话层", 5)
def encapsulate(self, data):
"""建立会话"""
session_id = "SESSION-20250105-12345"
session_data = f"[会话头|会话ID:{session_id}]{data}"
print(f"💬 {self.name}: 建立会话")
print(f" 会话ID: {session_id}")
return session_data
def decapsulate(self, data):
"""终止会话"""
start = data.find("]") + 1
print(f"💬 {self.name}: 解析会话信息")
return data[start:]
class PresentationLayer(OSILayer):
"""表示层:第6层"""
def __init__(self):
super().__init__("表示层", 6)
def encapsulate(self, data):
"""数据格式转换"""
# 这里简化为添加编码信息
formatted_data = f"[格式|编码:UTF-8|压缩:无|加密:无]{data}"
print(f"🎨 {self.name}: 数据格式处理")
print(f" 编码: UTF-8")
return formatted_data
def decapsulate(self, data):
"""数据格式还原"""
start = data.find("]") + 1
print(f"🎨 {self.name}: 数据格式还原")
return data[start:]
class ApplicationLayer(OSILayer):
"""应用层:第7层"""
def __init__(self):
super().__init__("应用层", 7)
def encapsulate(self, data):
"""生成HTTP请求"""
http_request = f"GET / HTTP/1.1\\nHost: example.com\\n\\n{data}"
print(f"📱 {self.name}: 生成HTTP请求")
print(f" 请求: GET / HTTP/1.1")
print(f" 主机: example.com")
return http_request
def decapsulate(self, data):
"""解析HTTP响应"""
print(f"📱 {self.name}: 解析HTTP响应")
return data
class OSIModel:
"""OSI七层模型"""
def __init__(self):
# 创建各层对象
self.layers = [
ApplicationLayer(), # 第7层
PresentationLayer(), # 第6层
SessionLayer(), # 第5层
TransportLayer(), # 第4层
NetworkLayer(), # 第3层
DataLinkLayer(), # 第2层
PhysicalLayer(), # 第1层
]
def send_data(self, data):
"""发送数据:从应用层到物理层"""
print("=" * 70)
print("📤 数据发送过程(封装)".center(70))
print("=" * 70)
print(f"\n原始数据: {data}\n")
current_data = data
# 从应用层到物理层,逐层封装
for layer in self.layers:
print(f"\n{'▼' * 35}")
current_data = layer.encapsulate(current_data)
if layer.layer_num > 1: # 物理层的输出太长,不显示完整数据
print(f" 数据长度: {len(current_data)} 字符")
print("\n" + "=" * 70)
return current_data
def receive_data(self, data):
"""接收数据:从物理层到应用层"""
print("\n" + "=" * 70)
print("📥 数据接收过程(解封装)".center(70))
print("=" * 70)
current_data = data
# 从物理层到应用层,逐层解封装
for layer in reversed(self.layers):
print(f"\n{'▲' * 35}")
current_data = layer.decapsulate(current_data)
print(f"\n最终数据: {current_data}")
print("=" * 70)
return current_data
def main():
"""主函数"""
print("=" * 70)
print("OSI七层模型数据封装演示".center(70))
print("=" * 70)
print("\n📚 本程序演示OSI七层模型的数据封装和解封装过程")
print()
# 创建OSI模型
osi = OSIModel()
# 要发送的数据
original_data = "Hello, Network World!"
print(f"🎯 准备发送数据: \"{original_data}\"")
print()
# 发送数据(封装过程)
transmitted_data = osi.send_data(original_data)
# 模拟数据传输
print("\n" + "⚡" * 35)
print(" 数据通过网络传输中...")
print("⚡" * 35)
# 接收数据(解封装过程)
received_data = osi.receive_data(transmitted_data)
# 验证
print("\n" + "=" * 70)
print("✅ 传输完成!".center(70))
print("=" * 70)
print(f"\n发送的数据: {original_data}")
print(f"接收的数据: {received_data}")
if "Hello, Network World!" in received_data:
print("\n🎉 数据传输成功!")
else:
print("\n❌ 数据传输失败!")
if __name__ == "__main__":
main()
运行程序
cd code/day03
python day03_osi_demo.py
预期输出
程序会详细展示数据在OSI七层模型中的封装和解封装过程,帮助你直观理解每一层的作用。
🎓 知识小结
今天学到了什么?
- ✅ OSI七层模型是网络通信的标准模型
- ✅ 每一层都有明确的职责
- ✅ 数据发送时逐层封装,接收时逐层解封装
- ✅ 分层的优点是降低复杂度、便于维护
OSI七层速记
| 层次 | 名称 | 关键词 | 协议示例 |
|---|---|---|---|
| 7 | 应用层 | 用户接口 | HTTP、FTP、DNS |
| 6 | 表示层 | 格式转换 | SSL、JPEG |
| 5 | 会话层 | 会话管理 | RPC、SQL |
| 4 | 传输层 | 端到端 | TCP、UDP |
| 3 | 网络层 | 路由寻址 | IP、ICMP |
| 2 | 数据链路层 | 帧传输 | Ethernet、WiFi |
| 1 | 物理层 | 比特流 | 网线、光纤 |
重要概念
- 封装(Encapsulation):发送数据时,逐层添加头部信息
- 解封装(Decapsulation):接收数据时,逐层移除头部信息
- PDU(Protocol Data Unit):协议数据单元
- 应用层:消息(Message)
- 传输层:段(Segment)
- 网络层:包(Packet)
- 数据链路层:帧(Frame)
- 物理层:比特(Bit)
💪 练习题
练习1:层次识别
以下操作分别在哪一层完成?
- 输入网址 www.baidu.com
- 将域名解析为IP地址
- 添加源端口和目标端口
- 选择路由路径
- 将数据转换为电信号
练习2:绘制封装过程
画出"发送一封邮件"的完整封装过程,标注每一层添加的信息。
练习3:思考题
- 为什么要分成7层?能不能只分3层或分10层?
- 如果没有分层,会有什么问题?
- 哪些层是软件实现的?哪些是硬件实现的?
练习4:代码扩展
修改演示程序,添加以下功能:
- 显示每层数据的大小变化
- 模拟数据在传输过程中丢失的情况
- 添加错误检测和重传机制
📚 扩展阅读
OSI vs TCP/IP模型
OSI是理论模型,TCP/IP是实际使用的模型:
OSI七层模型 TCP/IP四层模型
┌─────────────┐
│ 应用层 │ \ ┌─────────────┐
├─────────────┤ \ │ 应用层 │
│ 表示层 │ } ───> │ │
├─────────────┤ / │ │
│ 会话层 │ / └─────────────┘
├─────────────┤ ┌─────────────┐
│ 传输层 │ ─────> │ 传输层 │
├─────────────┤ └─────────────┘
│ 网络层 │ ─────> ┌─────────────┐
├─────────────┤ │ 网络层 │
│ 数据链路层 │ \ └─────────────┘
├─────────────┤ } ───> ┌─────────────┐
│ 物理层 │ / │ 网络接口层 │
└─────────────┘ └─────────────┘
明天我们将详细学习TCP/IP模型!
🎯 明天预告
第4天:TCP/IP四层模型
我们将学习:
- TCP/IP模型和OSI模型的区别
- TCP/IP各层的详细功能
- 实际网络中如何使用TCP/IP
- 编写程序分析真实的网络数据包
💡 今日金句:分层不是为了复杂化,而是为了简单化!
👉 上一天:网络的分类和拓扑结构 | 返回目录 | 下一天:TCP/IP四层模型