计算机网络基础:TCP/IP 协议栈笔记
本文最后更新于 22 天前,如有失效请评论区留言。

之前我们聊过 Shell、Git、数据结构这些 CS 基础,这次来补一个更底层的知识——TCP/IP 协议栈。不管你是做 Web 开发、写爬虫还是搞分布式系统,网络协议都是绕不开的。今天我们用学习笔记的方式,从上到下把四层模型过一遍,顺便用 Python socket 写个小程序加深理解。

一、TCP/IP 四层模型概览

你可能听过 OSI 七层模型,但在实际工程中我们更常说的是 TCP/IP 四层模型。它把网络通信抽象成四层,每一层各司其职:

  • Application Layer(应用层):HTTP、HTTPS、DNS、FTP、SMTP 等,我们写代码直接打交道的一层。
  • Transport Layer(传输层):TCP 和 UDP,负责端到端的可靠传输。
  • Internet Layer(网络层):IP、ICMP、ARP,负责路由和寻址,把数据包从源主机送到目的主机。
  • Network Access Layer(网络接入层):Ethernet、Wi-Fi,处理物理传输。

💡 简单记忆:应用层管「说什么」,传输层管「怎么可靠地送到」,网络层管「送到哪」,接入层管「用什么物理线路送」。

数据从应用层往下走的时候,每一层都会加上自己的 header,这个过程叫 encapsulation(封装)。到了对端再从下往上逐层拆 header,叫 decapsulation(解封装)。就像套娃一样,一层包一层。

二、IP 协议:网络层的核心

IP(Internet Protocol) 是整个互联网的基础。它做的事情很简单:给每个设备分配一个地址(IP address),然后把数据包从源地址路由到目的地址。

IPv4 地址是 32 位的,比如 192.168.1.1。因为地址不够用,后来又搞了 IPv6(128 位)。IP 协议本身是不可靠的——它只管「尽力而为」地把包送出去,不保证一定送到,也不保证顺序。所以才需要上层的 TCP 来保证可靠性。

一个 IP packet 的关键字段:

  • Version:IPv4 还是 IPv6
  • Source / Destination IP:源地址和目的地址
  • TTL(Time to Live):防止数据包在网络中无限循环,每经过一个路由器减 1
  • Protocol:上层协议类型,比如 TCP 是 6,UDP 是 17

三、TCP:可靠的传输层协议

TCP(Transmission Control Protocol) 是面向连接的、可靠的、基于字节流的传输层协议。它在 IP 的基础上加了一堆机制来保证数据不丢、不乱、不重复。

建立 TCP 连接需要三次握手,这是面试高频考点:

  1. SYN:客户端发一个 SYN 包(seq=x),表示「我要连接」
  2. SYN-ACK:服务端回一个 SYN-ACK 包(seq=y, ack=x+1),表示「收到,我也准备好了」
  3. ACK:客户端再发一个 ACK 包(ack=y+1),表示「好,开始传数据吧」

🤔 面试常问:为什么是三次而不是两次?因为两次握手无法确认客户端的接收能力。如果客户端的旧 SYN 包延迟到达,服务端会误开连接浪费资源。三次握手确保双方的发送和接收能力都没问题。

关闭连接需要四次挥手:

  1. 客户端发 FIN,表示「我不发了」
  2. 服务端回 ACK,表示「收到」(此时服务端可能还有数据要发)
  3. 服务端发 FIN,表示「我也不发了」
  4. 客户端回 ACK,然后进入 TIME_WAIT 状态等待 2MSL

为什么是四次?因为 TCP 是全双工的,每个方向需要单独关闭。

  • Sequence Number & ACK:每个字节都有序号,接收方确认收到
  • Retransmission(重传):超时没收到 ACK 就重传
  • Flow Control(流量控制):用 sliding window 控制发送速率
  • Congestion Control(拥塞控制):慢启动、拥塞避免、快速重传、快速恢复

四、UDP vs TCP

UDP(User Datagram Protocol) 是无连接的、不可靠的传输协议。听起来好像很弱,但它有自己的优势:

  • 没有握手和挥手,延迟更低
  • 没有重传机制,适合实时场景(视频通话、游戏、DNS 查询)
  • 头部开销小(8 字节 vs TCP 的 20+ 字节)

选择 TCP 还是 UDP 取决于你的场景:要可靠就用 TCP(HTTP、文件传输),要速度就用 UDP(实时音视频、IoT)。

五、应用层:HTTP 请求的一生

我们最常接触的应用层协议就是 HTTP。当你在浏览器输入一个 URL,背后发生了什么?

  1. DNS 解析:把域名(如 edryan.top)解析成 IP 地址
  2. TCP 三次握手:和服务器建立连接(HTTPS 还要 TLS 握手)
  3. 发送 HTTP 请求:GET /index.html HTTP/1.1
  4. 服务器处理并返回响应:HTTP/1.1 200 OK + HTML 内容
  5. 浏览器渲染:解析 HTML、CSS、JS,渲染页面
  6. TCP 四次挥手:关闭连接(或者 keep-alive 保持)

这个过程就是从应用层一路封装到网络接入层,经过路由器层层转发,到了服务器再解封装上去。

六、Python Socket 编程实战

说了这么多理论,不如动手写个代码。Python 的 socket 模块让我们可以直接操作传输层。下面是一个简单的 TCP echo server 和 client 的例子:

import socket

# 创建 TCP socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定地址和端口
server.bind(('0.0.0.0', 9999))
server.listen(5)
print("Server listening on port 9999...")

while True:
    # 等待客户端连接(三次握手在这里完成)
    conn, addr = server.accept()
    print(f"Connected by {addr}")

    while True:
        data = conn.recv(1024)  # 接收数据
        if not data:
            break
        print(f"Received: {data.decode()}")
        conn.sendall(data)      # 原样返回(echo)

    conn.close()  # 关闭连接(四次挥手)
    print(f"Disconnected: {addr}")
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 9999))  # 连接服务器(触发三次握手)

message = "Hello from TCP client!"
client.sendall(message.encode())     # 发送数据
print(f"Sent: {message}")

data = client.recv(1024)             # 接收 echo
print(f"Received: {data.decode()}")

client.close()  # 关闭连接

运行的时候先启动 server,再开 client。你会看到 server 收到消息后原样返回。在这个过程中,connect() 触发了三次握手,sendall() 的数据经过 TCP 分段、IP 封装、以太网帧封装后发送出去,close() 触发四次挥手。

import socket

# UDP Server
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # SOCK_DGRAM = UDP
server.bind(('0.0.0.0', 8888))
print("UDP server listening on port 8888...")

while True:
    data, addr = server.recvfrom(1024)  # 无需 listen/accept,直接收
    print(f"From {addr}: {data.decode()}")
    server.sendto(data, addr)           # 发送时需要指定目标地址

对比一下你会发现,UDP 的代码简单很多——没有 listen()accept()connect(),因为它不需要建立连接。这也对应了前面说的「无连接」特性。

七、常用网络调试工具

学网络不能光看理论,调试工具也得会用:

  • ping:测试主机之间的连通性,基于 ICMP 协议
  • traceroute(Linux)/tracert(Windows):追踪数据包经过的路由路径
  • netstat / ss:查看当前的网络连接和端口占用
  • curl:发送 HTTP 请求,调试 API
  • tcpdump / Wireshark:抓包分析,可以看到每一层的 header 信息

比如用 tcpdump 抓 TCP 三次握手:

sudo tcpdump -i eth0 -n 'tcp port 80' -c 6

你会看到 SYN、SYN-ACK、ACK 三个包,这就是我们前面讲的三次握手的真实体现。

八、总结

这篇文章我们过了一遍 TCP/IP 四层模型的核心概念:

  • 四层模型:应用层 → 传输层 → 网络层 → 网络接入层
  • IP 协议负责寻址和路由,不可靠但高效
  • TCP 通过三次握手建立连接,通过序号、确认、重传等机制保证可靠性
  • UDP 无连接、低延迟,适合实时场景
  • HTTP 请求背后是 DNS + TCP 握手 + 请求/响应 + 挥手的完整流程

建议大家自己动手用 Python socket 写一写,再配合 tcpdump 抓包看看,比纯看书记得牢多了。网络协议这块内容很深,今天我们只是入门,后续可以继续聊 HTTPS/TLS、HTTP/2、WebSocket 等进阶话题。

参考资料:《计算机网络:自顶向下方法》、RFC 793(TCP)、RFC 791(IP)

版权声明:除特殊说明,博客文章均为原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇