Python 网络编程:Socket、TCP、UDP、HTTP 服务器实战
Introduction
Socket 是网络编程的基础。本文从 TCP/UDP 基础讲起,搭建简单的 TCP 多客户端聊天服务器、实现 HTTP 服务器、以及使用 asyncio 实现异步网络编程。
---
Socket 基础
import socket
# TCP 服务器
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 9999))
server.listen(5)
print('TCP 服务器监听 :9999')
while True:
client, addr = server.accept()
print(f'客户端连接: {addr}')
data = client.recv(1024)
client.sendall(b'Hello, ' + data)
client.close()
# TCP 客户端
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 9999))
client.sendall(b'World')
response = client.recv(1024)
print('收到:', response.decode())
client.close()
TCP 多客户端聊天服务器
import socket, threading
clients = []
def broadcast(message, sender=None):
for client in clients:
if client != sender:
try:
client.sendall(message)
except:
clients.remove(client)
def handle_client(client):
while True:
try:
data = client.recv(1024)
if not data:
break
broadcast(data, sender=client)
except:
clients.remove(client)
client.close()
break
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()
print('聊天室服务器已启动')
while True:
client, addr = server.accept()
clients.append(client)
thread = threading.Thread(target=handle_client, args=(client,))
thread.daemon = True
thread.start()
UDP 服务器
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('0.0.0.0', 9999))
print('UDP 服务器监听 :9999')
while True:
data, addr = server.recvfrom(1024)
print(f'收到 {addr}: {data.decode()}')
server.sendto(b'ACK: ' + data, addr)
HTTP 服务器
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(b'<h1>Hello from Python HTTP Server</h1>')
elif self.path == '/api/status':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
self.wfile.write(json.dumps({'status': 'ok', 'clients': 5}).encode())
else:
self.send_error(404)
HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()
asyncio 异步网络编程
import asyncio
async def handle_client(reader, writer):
addr = writer.get_extra_info('peername')
print(f'客户端连接: {addr}')
while True:
data = await reader.read(1024)
if not data:
break
writer.write(data) # 回显
await writer.drain()
print(f'客户端断开: {addr}')
writer.close()
await writer.wait_closed()
async def main():
server = await asyncio.start_server(
handle_client, '0.0.0.0', 9999
)
print('异步服务器监听 :9999')
async with server:
await server.serve_forever()
asyncio.run(main())
常见问题
Q1: socket.AF_INET 和 SOCK_STREAM 什么意思?AF_INET 表示 IPv4,SOCK_STREAM 是 TCP(面向连接);SOCK_DGRAM 是 UDP(无连接)。
Q2: 为什么服务器要 setSocketOpt(SO_REUSEADDR)? 防止程序崩溃后端口被占用处于 TIME_WAIT 状态,设置为 1 可以立即重用端口。
Q3: asyncio 比 threading 好在哪?asyncio 是单线程协程,切换开销远小于线程,适合大量并发 I/O 连接场景(如聊天服务器、爬虫)。
延伸阅读
- Python asyncio 进阶
- WebSocket 实时通信
- HTTP/2 和 HTTP/3
---
作者:小马 | 绍大技术网 shaoda.net