我们将从最简单的概念开始,逐步深入到具体的代码实现,包括 TCP 和 UDP 两种最常用的协议。

(图片来源网络,侵删)
什么是 Socket?
你可以把 Socket 想象成一个“电话插座”,当你想打电话时,你需要:
- 一部电话(客户端)。
- 一个电话号码和端口(服务器的地址)。
- 拨号并建立连接(
connect)。 - 说话和听话(发送和接收数据)。
- 挂断电话(关闭连接)。
Socket 编程就是用代码实现这个过程,在 Python 中,我们使用内置的 socket 模块来完成这一切。
核心概念
在写代码前,需要理解几个关键概念:
- IP 地址:网络中设备的唯一地址,
0.0.1(本机地址)或168.1.100(局域网地址)。 - 端口号:同一台计算机上,可能有多个程序需要网络通信,端口号用来区分这些不同的程序(服务),范围是 0-65535,0-1023 是系统保留端口,Web 服务通常使用 80 或 443 端口。
- 协议:通信双方必须遵守的规则,最常见的两种是:
- TCP (Transmission Control Protocol):面向连接、可靠的协议,通信前必须先建立连接(三次握手),数据像水流一样有序、无丢失地到达,适合对数据准确性要求高的场景,如文件传输、网页浏览。
- UDP (User Datagram Protocol):无连接、不可靠的协议,直接把数据包发出去,不保证顺序、不保证到达、不保证重复,速度快,开销小,适合对实时性要求高但能容忍少量丢包的场景,如视频会议、在线游戏。
TCP 编程(可靠的连接)
TCP 编程模型是“客户端-服务器”模式,流程如下:

(图片来源网络,侵删)
服务器端:
socket():创建一个 socket 对象。bind():将 socket 绑定到指定的 IP 和端口。listen():开始监听,等待客户端连接。accept():阻塞式等待,接受一个客户端连接,返回一个新的 socket 对象和客户端地址。recv()/send():通过新的 socket 与客户端收发数据。close():关闭连接。
客户端:
socket():创建一个 socket 对象。connect():主动连接服务器的 IP 和端口。send()/recv():与服务器收发数据。close():关闭连接。
代码示例:一个简单的 TCP 聊天程序
我们将创建两个文件:server.py(服务器)和 client.py(客户端)。
server.py (服务器端)
# server.py
import socket
# 1. 创建 socket 对象
# AF_INET 表示使用 IPv4 地址
# SOCK_STREAM 表示使用 TCP 协议
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定 IP 地址和端口号
# 空字符串 '' 表示监听本机所有可用的网络接口
# 8888 是我们选择的端口号
server_address = ('', 8888)
server_socket.bind(server_address)
# 3. 开始监听,允许的最大连接数是 1
server_socket.listen(1)
print("服务器已启动,等待客户端连接...")
# 4. 阻塞式等待,接受客户端连接
# conn_socket 是一个新的 socket 对象,专门用于与这个客户端通信
# client_address 是客户端的地址 (IP, port)
conn_socket, client_address = server_socket.accept()
# 5. 与客户端收发数据
print(f"已连接客户端: {client_address}")
# 循环收发消息
while True:
# 接收客户端数据 (最大接收 1024 字节)
# recv() 是阻塞的,如果没有数据,程序会卡在这里
data = conn_socket.recv(1024)
# 如果客户端关闭连接,recv() 会返回空字节
if not data:
break
print(f"收到客户端消息: {data.decode('utf-8')}")
# 发送回复给客户端
response = "消息已收到!"
conn_socket.sendall(response.encode('utf-8'))
# 6. 关闭连接
conn_socket.close()
server_socket.close()
print("服务器已关闭。")
client.py (客户端)
# client.py
import socket
# 1. 创建 socket 对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 连接服务器的 IP 地址和端口号
# 127.0.0.1 是本机地址,如果你想连接另一台电脑,换成它的 IP
server_address = ('127.0.0.1', 8888)
print(f"正在连接服务器 {server_address}...")
try:
client_socket.connect(server_address)
print("已连接到服务器!")
# 3. 与服务器收发数据
while True:
# 从用户输入获取消息
message = input("请输入要发送的消息 (输入 'exit' 退出): ")
if message.lower() == 'exit':
break
# 发送消息到服务器 (必须是字节串)
client_socket.sendall(message.encode('utf-8'))
# 接收服务器的回复
data = client_socket.recv(1024)
print(f"收到服务器回复: {data.decode('utf-8')}")
except ConnectionRefusedError:
print("连接失败!请确保服务器已启动。")
finally:
# 4. 关闭连接
client_socket.close()
print("客户端已关闭。")
如何运行:

(图片来源网络,侵删)
- 先运行
python server.py,你会看到 "服务器已启动,等待客户端连接..."。 - 再打开一个新的终端,运行
python client.py,客户端会连接到服务器,然后你就可以在客户端输入消息,服务器会收到并回复。
UDP 编程(无连接的通信)
UDP 编程比 TCP 简单得多,因为它没有 listen() 和 accept() 的连接建立过程,它就像发信件,直接把信(数据包)发出去,不管对方收到没有。
流程:
socket():创建 socket 对象。sendto():直接将数据包发送到指定的 IP 和端口。recvfrom():接收来自任何 IP 和端口的数据包。
代码示例:一个简单的 UDP 聊天程序
udp_server.py (UDP 服务器)
# udp_server.py
import socket
# 1. 创建 socket 对象
# SOCK_DGRAM 表示使用 UDP 协议
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 绑定 IP 地址和端口号
server_address = ('', 8889)
server_socket.bind(server_address)
print("UDP 服务器已启动,等待接收数据...")
# 3. 循环接收数据
while True:
# recvfrom() 会返回数据和发送方的地址
# 1024 是接收缓冲区大小
data, client_address = server_socket.recvfrom(1024)
if not data:
break
print(f"从 {client_address} 收到消息: {data.decode('utf-8')}")
# 4. 使用 sendto() 发送回复
response = "UDP 消息已收到!"
server_socket.sendto(response.encode('utf-8'), client_address)
# 5. 关闭 socket (虽然这个例子是死循环,不会执行到这里)
server_socket.close()
udp_client.py (UDP 客户端)
# udp_client.py
import socket
# 1. 创建 socket 对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 定义服务器的地址
server_address = ('127.0.0.1', 8889)
print("UDP 客户端已启动,可以发送消息。")
# 3. 循环发送和接收
while True:
message = input("请输入要发送的消息 (输入 'exit' 退出): ")
if message.lower() == 'exit':
break
# 4. 使用 sendto() 发送数据
client_socket.sendto(message.encode('utf-8'), server_address)
# 5. 使用 recvfrom() 接收回复
data, _ = client_socket.recvfrom(1024) # _ 用于忽略发送方地址,因为我们知道是服务器
print(f"收到服务器回复: {data.decode('utf-8')}")
# 6. 关闭 socket
client_socket.close()
print("UDP 客户端已关闭。")
如何运行:
和 TCP 一样,先运行 python udp_server.py,再运行 python udp_client.py 进行测试。
TCP vs. UDP 总结
| 特性 | TCP (面向连接) | UDP (无连接) |
|---|---|---|
| 可靠性 | 高,确保数据无差错、不丢失、不重复、按序到达。 | 低,不保证可靠性,可能丢包、乱序。 |
| 速度 | 慢,因为需要建立连接、维护状态、重传机制。 | 快,没有连接开销,协议简单。 |
| 资源占用 | 高,需要维护连接状态,占用较多系统资源。 | 低,无需维护连接,资源开销小。 |
| 通信模式 | 一对一(一个 socket 只能连接一个客户端)。 | 一对多、多对多(广播、多播)。 |
| 应用场景 | 文件传输、网页浏览、邮件发送(HTTP, FTP, SMTP)。 | 视频会议、在线游戏、DNS查询、直播。 |
希望这个详细的教程能帮助你理解 Python 的 Socket 基本编程!从 TCP 开始练习是最好的选择,因为它能让你更好地理解网络通信的完整流程。
