网络编程基础
网络编程是让不同主机上的程序通过网络互相通信的技术。理解底层的 TCP/IP 协议和 Socket 抽象层,是编写网络程序的基础。
架构模式
- B/S(Browser/Server):客户端是浏览器,通过 HTTP/HTTPS 与服务器通信。无需安装客户端,但功能受浏览器限制。
- C/S(Client/Server):专用客户端与服务器通信。可定制协议,功能更丰富,但需要安装客户端。
OSI 七层模型
OSI(Open Systems Interconnection)参考模型把网络通信分为七个抽象层,各层职责清晰:
| 层级 | 名称 | 协议/功能举例 | 数据单元 |
|---|---|---|---|
| 7 | 应用层 | HTTP、FTP、SMTP、DNS | 数据 |
| 6 | 表示层 | 加密、压缩、编码转换 | 数据 |
| 5 | 会话层 | 会话建立与管理 | 数据 |
| 4 | 传输层 | TCP、UDP | 段(Segment) |
| 3 | 网络层 | IP、ARP、ICMP | 包(Packet) |
| 2 | 数据链路层 | Ethernet、MAC 地址 | 帧(Frame) |
| 1 | 物理层 | 电缆、光纤、无线信号 | 位(Bit) |
- 发送时数据从上至下逐层封装(添加各层头部)。
- 接收时数据从下至上逐层解封装。
TCP/IP 协议族
实际互联网使用的是 TCP/IP 协议族(四层模型):
| TCP/IP 层 | 对应 OSI 层 | 主要协议 |
|---|---|---|
| 应用层 | 5~7 层 | HTTP、HTTPS、FTP、DNS、SMTP |
| 传输层 | 4 层 | TCP、UDP |
| 网络层 | 3 层 | IP、ARP、ICMP |
| 网络接口层 | 1~2 层 | Ethernet、Wi-Fi |
IP 地址与端口
- IP 地址:32 位二进制(IPv4),标识网络中的主机位置。格式:
192.168.1.100。127.0.0.1:本地回环地址,用于本机自测。0.0.0.0:监听所有网络接口。255.255.255.255:广播地址。
- 端口号:0~65535,标识主机上的具体进程/服务。
- 知名端口(0~1023):HTTP 80、HTTPS 443、SSH 22、FTP 21、SMTP 25。
- 动态端口(49152~65535):客户端随机分配。
TCP vs UDP
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 保证顺序、无丢失 | 不保证 |
| 速度 | 较慢(有确认机制) | 较快 |
| 适用场景 | Web、文件传输、邮件 | 视频流、DNS、游戏 |
TCP 三次握手与四次挥手
三次握手(建立连接)
客户端 服务端
| ---SYN(seq=x)---> | 第一次:客户端发 SYN,进入 SYN_SENT
| <--SYN+ACK(seq=y,ack=x+1)-- | 第二次:服务端发 SYN+ACK,进入 SYN_RECV
| ---ACK(ack=y+1)--> | 第三次:客户端发 ACK,双方进入 ESTABLISHED为什么三次? 两次握手无法确认客户端的接收能力;三次握手可以双向确认通信正常。
四次挥手(关闭连接)
主动关闭方 被动关闭方
| ---FIN---> | 第一次:发送 FIN,进入 FIN_WAIT_1
| <--ACK--- | 第二次:回复 ACK,进入 CLOSE_WAIT
| <--FIN--- | 第三次:发送 FIN,进入 LAST_ACK
| ---ACK---> | 第四次:回复 ACK,等待 2MSL 后关闭为什么四次? TCP 是全双工的,关闭时两个方向各需要一次 FIN+ACK。
Socket 抽象层
Socket 是操作系统提供的网络编程接口,对应用程序屏蔽了 TCP/IP 的底层细节。
AF_INET:IPv4 网络套接字(最常用)AF_INET6:IPv6 网络套接字AF_UNIX:Unix 域套接字,用于同机进程间通信SOCK_STREAM:TCP 套接字(面向连接,可靠)SOCK_DGRAM:UDP 套接字(无连接,快速)
常用端口速查
import socket
# 根据服务名查端口
print(socket.getservbyname("http")) # 80
print(socket.getservbyname("https")) # 443
print(socket.getservbyname("ssh")) # 22
# 根据端口查服务名
print(socket.getservbyport(80)) # "http"
# 获取本机 IP
print(socket.gethostbyname(socket.gethostname()))下一节 Socket 编程 将介绍如何用 Python 的 socket 模块实现 TCP/UDP 通信。
最后更新于