
在 Python(含 2.6)中模拟 Go 的 io.Copy 行为,需手动循环读写套接字数据并妥善处理 EOF 与异常;推荐使用双线程分别转发两个方向的数据流,并加入缓冲区控制和连接关闭逻辑。
在 python(含 2.6)中模拟 go 的 `io.copy` 行为,需手动循环读写套接字数据并妥善处理 eof 与异常;推荐使用双线程分别转发两个方向的数据流,并加入缓冲区控制和连接关闭逻辑。
在构建 TCP 代理(如反向代理、调试中间件或协议转换网关)时,一个核心需求是高效、可靠地将两个已建立的 socket 连接双向桥接——即把 conn1 接收到的数据无损转发给 conn2,同时将 conn2 的响应原样回传给 conn1。Go 语言通过 io.Copy(conn1, conn2) 即可简洁完成单向流复制,而 Python 标准库未提供完全等价的阻塞式原子函数,但可通过轻量级循环 + 多线程轻松实现同等语义。
以下是一个兼容 Python 2.6 的 CopyProxy 函数实现:
import threading
BUFFER_SIZE = 8192 # 推荐值:兼顾吞吐与内存占用
def copy_proxy(src, dst):
"""将 src 套接字的数据持续读取并写入 dst,遇 EOF 或异常时安全关闭双方连接"""
try:
while True:
data = src.recv(BUFFER_SIZE)
if not data: # 对端正常关闭(FIN)
break
dst.sendall(data) # 使用 sendall 避免部分发送
except (IOError, OSError, socket.error):
pass # 网络中断、连接重置等异常,静默退出
finally:
try:
src.close()
except:
pass
try:
dst.close()
except:
pass使用时,启动两个独立线程分别处理正向与反向流:
import socket import threading # 示例:假设 conn1 是客户端连接,conn2 是上游服务端连接 # conn1, conn2 = accept_client(), connect_to_backend() t1 = threading.Thread(target=copy_proxy, args=(conn1, conn2)) t2 = threading.Thread(target=copy_proxy, args=(conn2, conn1)) t1.daemon = True # 确保主线程退出时子线程自动终止 t2.daemon = True t1.start() t2.start() # 主线程可等待代理结束(例如监听某事件),或直接继续其他逻辑 t1.join() t2.join()
⚠️ 关键注意事项:
立即学习“Python免费学习笔记(深入)”;
-
必须使用
sendall()而非send():后者可能仅发送部分数据,导致协议错乱; -
recv()返回空字符串''表示对端已关闭连接(EOF),此时应主动退出循环并关闭本端; -
异常捕获需覆盖
IOError/OSError/socket.error(Python 2.6 中异常类型较分散); -
显式
close()放在finally块中,确保无论正常退出还是异常中断,资源均被释放; -
建议设置
daemon=True,防止代理线程阻塞主程序退出; - 若需更高可靠性(如断线重连、流量统计、超时控制),应在该基础结构上扩展,而非修改核心循环逻辑。
该方案简洁、可移植、符合 Python 2.6 语法约束,是构建轻量级 TCP 代理的实用起点。


















