TCP/UDP 网络编程
本教程共 70 篇 · 第 58 篇 · 更新于 2026-07-22 · 约 5 分钟阅读
58. TCP/UDP 网络编程
本节目标:理解 socket 的基本概念,能写出简单的 TCP 服务端和客户端,知道 UDP 和 TCP 的区别。
网络编程听起来高大上,本质就是两台电脑通过网络「打电话」。Python 把底层复杂的网络协议封装成了 socket 模块,你只需要几十行代码就能让两台机器聊起来。
Socket 是什么
Socket(套接字)是操作系统提供的网络通信接口。你可以把它想象成电话机的插孔:一边是程序,一边是网络。通过 socket,程序可以发送和接收数据。
创建 socket 需要指定三个要素:
- 地址族:
AF_INET表示 IPv4,AF_INET6表示 IPv6。 - 协议类型:
SOCK_STREAM表示 TCP,SOCK_DGRAM表示 UDP。 - 协议编号:通常填 0,让系统自动选择。
import socket
# TCP socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
TCP 客户端
TCP 是面向连接的可靠协议,适合传输文件、网页等不容丢数据的场景。客户端的角色是主动发起连接。
下面这段代码访问百度首页,把响应保存到本地:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('www.baidu.com', 80))
request = b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n'
s.send(request)
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
s.close()
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
with open('baidu.html', 'wb') as f:
f.write(html)
代码拆解:
connect((host, port))建立 TCP 连接,参数是元组。send()发送字节流,HTTP 请求必须是字节串。recv(1024)每次最多收 1024 字节,循环直到收完。close()关闭连接,释放资源。
Tip实际项目里很少直接用 socket 写 HTTP 请求,一般用
requests或urllib。但理解底层原理后,你再看高层库的源码就不懵了。
TCP 服务端
服务端需要绑定一个端口并监听连接。每来一个客户端,就创建新的 socket 专门跟它通信。
import socket
import threading
def handle_client(sock, addr):
print(f"接受连接: {addr}")
sock.send(b"Welcome!\n")
while True:
data = sock.recv(1024)
if not data or data.decode('utf-8').strip() == 'exit':
break
sock.send(f"Echo: {data.decode('utf-8')}".encode('utf-8'))
sock.close()
print(f"连接关闭: {addr}")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 9999))
s.listen(5)
print("等待连接...")
while True:
sock, addr = s.accept()
t = threading.Thread(target=handle_client, args=(sock, addr))
t.start()
关键点:
bind()绑定本机地址和端口。127.0.0.1只接受本机连接,0.0.0.0接受所有网卡。listen(5)设置等待队列长度,最多允许 5 个连接排队。accept()阻塞等待客户端,返回新的 socket 和客户端地址。- 每个连接开一个新线程处理,否则服务端一次只能服务一个客户端。
Warning1024 以下的端口通常需要管理员权限才能绑定。测试时尽量用 8000、9000 这样的高位端口,避免冲突。
UDP 编程
UDP 不建立连接,直接发数据包,不保证送达,但速度更快。视频直播、DNS 查询、在线游戏常用 UDP。
服务端:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 9999))
print("等待 UDP 消息...")
while True:
data, addr = s.recvfrom(1024)
print(f"来自 {addr}: {data.decode('utf-8')}")
s.sendto(b"Received: " + data, addr)
客户端:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for msg in [b'Hello', b'World']:
s.sendto(msg, ('127.0.0.1', 9999))
print(s.recv(1024).decode('utf-8'))
s.close()
UDP 不需要 connect() 和 listen(),收发用 sendto() 和 recvfrom(),每次都要指定地址。
TCP vs UDP 速查
| 特性 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接 | 无连接 |
| 可靠性 | 保证送达、有序 | 不保证 |
| 速度 | 较慢(有握手和确认) | 较快 |
| 适用场景 | 文件传输、网页浏览 | 视频流、即时通讯、游戏 |
小结
socket.socket()创建套接字,AF_INET+SOCK_STREAM是 TCP 标配。- TCP 客户端用
connect()发起连接,服务端用bind()+listen()+accept()等待连接。 - UDP 更轻量,直接用
sendto()/recvfrom()收发数据包。 - 生产环境的服务端通常需要多线程或多进程处理并发连接。
来源:参考了 runoob「Python3 网络编程」、liaoxuefeng「19.2. TCP编程/19.3. UDP编程」等,改写后所得。