
在 Python(含 2.6)中,可通过自定义循环读写 + 多线程方式模拟 Go 的 io.Copy,实现两个 socket 间无缓冲、低开销的双向数据转发。
在 python(含 2.6)中,可通过自定义循环读写 + 多线程方式模拟 go 的 `io.copy`,实现两个 socket 间无缓冲、低开销的双向数据转发。
Go 语言中 io.Copy(dst, src) 提供了简洁、阻塞式的数据流复制能力,常用于代理、隧道等场景。Python 标准库虽无完全等价的单函数,但可通过轻量级循环 + socket.recv()/socket.send() 配合多线程,精准复现其行为。
以下是一个兼容 Python 2.6 的可靠实现:
import threading
BUFFER_SIZE = 8192
def copy_proxy(src, dst):
"""将 src socket 的数据持续读取并写入 dst socket,遇 EOF 或异常时安全关闭双方连接"""
try:
while True:
data = src.recv(BUFFER_SIZE)
if not data: # 对端关闭连接(EOF)
break
dst.sendall(data) # 使用 sendall 确保全部数据发出
except (IOError, OSError, socket.error):
pass # 忽略网络中断、连接重置等常见错误
finally:
try:
src.close()
except:
pass
try:
dst.close()
except:
pass使用时需启动两个并发线程,分别处理正向与反向数据流:
import socket # 示例:建立两个已连接的 socket(如 client_conn 和 upstream_conn) # conn1 = accepted client socket # conn2 = connected upstream server socket 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():send()可能仅发送部分数据,而sendall()会重试直至全部写入或出错,更贴近io.Copy的语义; -
显式关闭逻辑置于
finally块中:确保无论是否异常,连接都能被释放,防止文件描述符泄漏; -
线程设为
daemon=True:避免代理进程因后台线程未退出而挂起; -
BUFFER_SIZE建议设为 4096–8192 字节:兼顾吞吐与内存占用,在 Python 2.6 中尤其重要; - 不依赖第三方库:该方案纯标准库实现,完全兼容 Python 2.6 及以上版本。
此模式已广泛应用于轻量 TCP 代理、调试中间件和协议桥接工具中,兼具简洁性、可控性与可维护性。


















