You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python AsyncIO协议创建报错:存在Transport却提示参数缺失

解决你的asyncio.Proxy错误

让我来帮你拆解这个问题——这个错误看起来有点绕,但核心是两个对asyncio.Protocol工作机制的误解:

错误1:工厂函数返回的是类而非实例

你在创建目标服务器连接时写了:

server_connection = loop.create_connection(
    lambda: ProxyForwardProtocol,
    host="127.0.0.1",
    port=25575)

这里的lambda返回的是ProxyForwardProtocol这个类本身,而不是它的实例。asyncio要求create_connection的第一个参数是一个返回Protocol实例的工厂函数,当asyncio尝试调用这个类的connection_made方法时,会把它当成类方法调用,而不是实例方法:

  • 实例方法connection_made(self, transport)需要两个参数(self和transport)
  • 但此时调用时只传入了transport作为第一个参数,所以Python会报错说缺少transport参数(因为它把transport当成了self,然后找不到第二个参数)

错误2:ProxyForwardProtocol的__init__错误地要求transport参数

asyncio的Protocol实例的transport是通过connection_made方法传递的,不是在初始化时传入的。你的ProxyForwardProtocol定义了需要transport的构造函数,这会导致即使你返回实例,也会因为缺少参数而报错。

额外的架构优化建议

你在ClientProxyProtocol的__init__中就创建目标服务器连接,这其实不太合理——因为此时客户端的连接还没建立(connection_made还没触发),更好的时机是在connection_made中创建目标连接,这样你能确保客户端的transport已经就绪。

修正后的代码示例

import asyncio
import socket

users = {}

class UserConnection(object):
    def __init__(self, client_socket, proxy_socket, peername):
        self.client_socket = client_socket
        self.proxy_socket = proxy_socket
        self.peername = peername

class ClientProxyProtocol(asyncio.Protocol):
    def __init__(self):
        self.transport = None
        self.session = None
        self.proto_forward = None  # 保存目标服务器的Protocol实例

    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        client_socket = transport.get_extra_info('socket')
        self.session = UserConnection(client_socket, None, peername)
        print('Connection from {}'.format(peername))
        self.transport = transport
        
        # 移到connection_made中创建目标连接,确保客户端连接已就绪
        server_connection = loop.create_connection(
            lambda: ProxyForwardProtocol(self),  # 传递当前ClientProxy实例用于双向通信
            host="127.0.0.1",
            port=25575)
        task = loop.create_task(server_connection)
        task.add_done_callback(self.handle_proxy_connection)

    def handle_proxy_connection(self, task):
        trans, proto = task.result()
        proxy_socket = trans.get_extra_info("socket")
        self.session.proxy_socket = proxy_socket
        self.proto_forward = proto  # 保存目标端的Protocol,方便后续转发数据
        users[proxy_socket] = self.session
        print(f"Connected to target server: {trans}")

    def data_received(self, data):
        message = data.decode('utf-8', errors='replace')
        print(f'Data from client {self.session.peername}: {message!r}')
        # 转发数据到目标服务器
        if self.proto_forward and self.proto_forward.transport:
            self.proto_forward.transport.write(data)

    def connection_lost(self, exc):
        print(f'Close client socket for {self.session.peername}')
        self.transport.close()
        # 关闭目标服务器连接
        if self.proto_forward and self.proto_forward.transport:
            self.proto_forward.transport.close()

class ProxyForwardProtocol(asyncio.Protocol):
    def __init__(self, client_proxy):
        self.transport = None
        self.client_proxy = client_proxy  # 保存客户端的Proxy实例,用于回传数据

    def connection_made(self, transport):
        self.transport = transport
        proxy_socket = transport.get_extra_info("socket")
        print(f"Forward connection established: {proxy_socket.getpeername()}")

    def data_received(self, data):
        message = data.decode('utf-8', errors='replace')
        print(f'Data from target server: {message!r}')
        # 回传数据到客户端
        if self.client_proxy and self.client_proxy.transport:
            self.client_proxy.transport.write(data)

    def connection_lost(self, exc):
        print("Closing forward connection")
        self.transport.close()
        # 关闭客户端连接
        if self.client_proxy and self.client_proxy.transport:
            self.client_proxy.transport.close()

loop = asyncio.get_event_loop()
coro = loop.create_server(ClientProxyProtocol, '127.0.0.1', 25565)
server = loop.run_until_complete(coro)

print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

关键修改点说明

  1. 把lambda: ProxyForwardProtocol改成lambda: ProxyForwardProtocol(self),返回实例同时传递客户端Proxy实例,方便双向数据转发
  2. 删除了ProxyForwardProtocol中需要transport的构造函数,改为接收客户端Proxy实例用于通信
  3. 将目标服务器连接的创建移到ClientProxyProtocol.connection_made中,确保客户端连接已建立
  4. 添加了数据转发逻辑,让代理真正实现双向通信(你原来的代码只打印数据,没有转发)

内容的提问来源于stack exchange,提问作者huhnmonster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:07:45