Python3 网络编程
Python3 学习笔记 · 整理自菜鸟教程
一句话
Python 通过 socket 模块实现基于 TCP/UDP 的网络通信,socket 是应用层与传输层之间的编程接口,负责建立连接、收发数据。
要点
- 两个核心协议:TCP(可靠、面向连接,如网页、文件传输)和 UDP(不可靠、无连接,如视频、DNS)。
socket.socket(family, type) 创建套接字:AF_INET(IPv4)、SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)。
- TCP 服务端四步:
bind 绑定地址 → listen 监听 → accept 接受连接 → recv/send 收发。
- TCP 客户端三步:
connect 连接 → send/recv 收发 → close 关闭。
- UDP 不需要连接:服务端
bind 后用 recvfrom/sendto,客户端直接 sendto/recvfrom。
- 数据以字节(bytes)传输,收发都要 encode/decode。
- 服务端常开多线程或多进程处理多客户端(见 45-Python3多线程)。
语法 / 常用方法
| 语法/方法 |
说明 |
示例 |
socket.socket(family, type) |
创建套接字 |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
s.bind((host, port)) |
绑定 IP 和端口 |
s.bind(('127.0.0.1', 9999)) |
s.listen(n) |
开始监听,n 为最大等待连接数 |
s.listen(5) |
s.accept() |
接受连接,返回 (客户端socket, 地址) |
conn, addr = s.accept() |
s.connect((host, port)) |
客户端连接服务器 |
s.connect(('127.0.0.1', 9999)) |
s.send(data) / s.sendall(data) |
发送字节数据,sendall 确保全发 |
conn.sendall(b'hello') |
s.recv(bufsize) |
接收数据,返回 bytes |
data = conn.recv(1024) |
s.recvfrom(bufsize) |
UDP 接收,返回 (数据, 地址) |
data, addr = s.recvfrom(1024) |
s.sendto(data, addr) |
UDP 发送到指定地址 |
s.sendto(b'hi', addr) |
s.close() |
关闭套接字 |
s.close() |
s.settimeout(t) |
设置超时秒数,超时抛 socket.timeout |
s.settimeout(5) |
socket.gethostname() |
获取本机主机名 |
socket.gethostname() |
socket.gethostbyname(name) |
域名解析为 IP |
socket.gethostbyname('www.baidu.com') |
with socket.socket(...) as s |
上下文管理,自动关闭 |
with socket.socket() as s: |
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(('127.0.0.1', 9999)) server.listen(5) print('服务端已启动,等待连接...')
while True: conn, addr = server.accept() print('客户端接入:', addr) conn.sendall(b'Welcome to Python TCP!') data = conn.recv(1024).decode('utf-8') print('收到:', data) conn.close()
|
1 2 3 4 5 6 7 8 9
| import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('127.0.0.1', 9999)) msg = client.recv(1024).decode('utf-8') print('服务器说:', msg) client.sendall('你好,服务器'.encode('utf-8')) client.close()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import socket
udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_server.bind(('127.0.0.1', 8888)) data, addr = udp_server.recvfrom(1024) print('UDP 收到:', data.decode(), '来自', addr) udp_server.sendto(b'pong', addr)
udp_client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_client.sendto('ping'.encode(), ('127.0.0.1', 8888)) resp, _ = udp_client.recvfrom(1024) print('UDP 响应:', resp.decode())
|
易错点
recv 可能一次收不全(TCP 流式),大消息要循环接收或约定长度/结束标记。
send 不保证一次发完,可靠发送用 sendall。
- 端口被占用会报
Address already in use,换端口或先关掉旧进程。
- 收发的是 bytes:字符串必须
.encode(),收回来要 .decode(),编码不一致会乱码。
- 服务端
accept 是阻塞的,单线程只能服务一个客户端,需多线程处理。
- 网络异常(对方断开)会抛异常,客户端代码要加 try/except,防止程序崩溃。