网络编程是连接程序与世界的桥梁。从底层的 socket 到高层的 HTTP 请求,本文带你掌握 Python 中网络通信的每个层次。
目录
- 网络编程层次概览
- Socket 基础:TCP 客户端/服务端
- UDP 编程:无连接通信
- HTTP 客户端:requests vs urllib
- 异步 HTTP:aiohttp
- 用 Python 写 Web 服务器
- WebSocket 实时通信
- 网络调试技巧
1. 网络编程层次概览
应用层:HTTP、FTP、DNS
│
传输层:TCP(可靠连接)、UDP(无连接)
│
网络层:IP(寻址与路由)
│
链路层:以太网、WiFi
Python 可在每个层次编程:
| 层次 | Python 工具 | 难度 |
|---|---|---|
| 应用层(HTTP) | requests, aiohttp, urllib | ⭐⭐ |
| 传输层 | socket | ⭐⭐⭐ |
| 底层 | scapy(数据包操作) | ⭐⭐⭐⭐ |
2. Socket 基础:TCP 客户端/服务端
2.1 TCP 服务端
import socket
import threading
def handle_client(conn, addr):
"""处理客户端连接"""
print(f"客户端 {addr} 已连接")
with conn:
while True:
data = conn.recv(1024)
if not data:
break
print(f"收到: {data.decode()}")
conn.sendall(b"Echo: " + data)
print(f"客户端 {addr} 已断开")
def start_server(host="0.0.0.0", port=8888):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(5)
print(f"服务器启动于 {host}:{port}")
while True:
conn, addr = s.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
if __name__ == "__main__":
start_server()
2.2 TCP 客户端
import socket
def send_message(message, host="127.0.0.1", port=8888):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, port))
s.sendall(message.encode())
response = s.recv(1024)
print(f"响应: {response.decode()}")
send_message("Hello, Server!")
2.3 使用 selectors 实现高效 I/O(单线程多连接)
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock):
conn, addr = sock.accept()
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn):
data = conn.recv(1024)
if data:
conn.send(data)
else:
sel.unregister(conn)
conn.close()
server = socket.socket()
server.bind(("0.0.0.0", 8888))
server.listen()
server.setblocking(False)
sel.register(server, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj)
3. UDP 编程:无连接通信
import socket
# UDP 服务端
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind(("0.0.0.0", 9999))
print("UDP 服务器启动")
while True:
data, addr = s.recvfrom(1024)
print(f"来自 {addr}: {data.decode()}")
s.sendto(b"Received: " + data, addr)
# UDP 客户端
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.sendto(b"Hello UDP", ("127.0.0.1", 9999))
data, _ = s.recvfrom(1024)
print(data.decode())
4. HTTP 客户端:requests vs urllib
4.1 requests(最常用)
import requests
# GET
resp = requests.get("https://api.github.com/users/python")
print(resp.status_code)
print(resp.json()["public_repos"])
# 带参数
resp = requests.get("https://httpbin.org/get", params={"key": "value"})
# POST JSON
resp = requests.post(
"https://httpbin.org/post",
json={"name": "Alice", "age": 25},
headers={"Authorization": "Bearer token123"},
)
# 下载文件
resp = requests.get("https://example.com/large.zip", stream=True)
with open("large.zip", "wb") as f:
for chunk in resp.iter_content(chunk_size=8192):
f.write(chunk)
# Session(保持 cookies/连接池)
with requests.Session() as s:
s.headers.update({"User-Agent": "MyApp/1.0"})
s.get("https://example.com/login")
4.2 urllib(标准库,无需安装)
import urllib.request
import urllib.parse
# GET
with urllib.request.urlopen("https://httpbin.org/get") as resp:
print(resp.read().decode())
# POST
data = urllib.parse.urlencode({"key": "value"}).encode()
req = urllib.request.Request("https://httpbin.org/post", data=data, method="POST")
with urllib.request.urlopen(req) as resp:
print(resp.read().decode())
4.3 httpx(现代化 HTTP 客户端)
# pip install httpx
import httpx
# 同步 API(兼容 requests)
resp = httpx.get("https://api.example.com/items")
# 异步 API(原生支持 async/await)
async with httpx.AsyncClient() as client:
resp = await client.get("https://api.example.com/items")
print(resp.json())
# HTTP/2 支持
client = httpx.Client(http2=True)
5. 异步 HTTP:aiohttp
# pip install aiohttp
import aiohttp
import asyncio
async def fetch_all(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch_one(session, url) for url in urls]
return await asyncio.gather(*tasks)
async def fetch_one(session, url):
async with session.get(url) as resp:
return await resp.text()
urls = ["https://httpbin.org/get"] * 5
results = asyncio.run(fetch_all(urls))
print(f"获取 {len(results)} 个页面")
6. 用 Python 写 Web 服务器
6.1 最简 HTTP 服务器
# 一行命令启动文件服务器
# python -m http.server 8000
# 程序化使用
from http.server import HTTPServer, SimpleHTTPRequestHandler
server = HTTPServer(("0.0.0.0", 8000), SimpleHTTPRequestHandler)
print("Serving on port 8000")
server.serve_forever()
6.2 自定义请求处理
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
class APIHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/api/users":
data = [{"id": 1, "name": "Alice"}]
self._send_json(data)
else:
self.send_error(404)
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
data = json.loads(body)
self.send_response(201)
self._send_json({"created": True, "data": data})
def _send_json(self, data):
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(data).encode())
server = HTTPServer(("0.0.0.0", 8000), APIHandler)
server.serve_forever()
7. WebSocket 实时通信
# pip install websockets
import asyncio
import websockets
async def handler(websocket, path):
async for message in websocket:
print(f"收到: {message}")
await websocket.send(f"Echo: {message}")
async def main():
async with websockets.serve(handler, "localhost", 8765):
print("WebSocket server on ws://localhost:8765")
await asyncio.Future() # 永远运行
asyncio.run(main())
# 客户端
async def ws_client():
async with websockets.connect("ws://localhost:8765") as ws:
await ws.send("Hello WebSocket!")
response = await ws.recv()
print(response)
asyncio.run(ws_client())
8. 网络调试技巧
# 1. 查看 DNS 解析
import socket
print(socket.gethostbyname("example.com"))
print(socket.getaddrinfo("example.com", 80))
# 2. 获取本机 IP
hostname = socket.gethostname()
print(socket.gethostbyname(hostname))
# 3. 端口是否开放
sock = socket.socket()
result = sock.connect_ex(("localhost", 5432))
print("开放" if result == 0 else "关闭")
延伸阅读
- Python asyncio 极速异步编程完全指南 —— 异步网络核心
- Python Web 框架:FastAPI 实战 —— 高层 Web 开发
- Python 并发与性能深度指南 —— 高并发网络服务
网络编程的核心不在于记住 API,而在于理解 TCP 连接的三次握手、HTTP 的请求/响应模型、以及 I/O 类型(阻塞/非阻塞/异步)的差异。掌握这些,任何网络库都能快速上手。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。