令人困惑的问题,异步与循环内的循环

时间:2020-05-18 12:39:38

标签: python sockets asynchronous python-asyncio

我正在尝试开发一种“反向代理”类型的东西,并且我差不多完成了。但是,我遇到了一个问题。我有两台服务器。运行实际源的主服务器(服务器A)和客户端将连接到的代理服务器(服务器B)。

基本上,我的设计如下:

客户端连接到服务器B(代理服务器)后...

  1. 客户端开始将其数据包发送到服务器B。

  2. 服务器B将其数据包发送到服务器A

  3. 服务器A接收到它们的数据包,对其进行适当的解析(这是实际的来源),然后将响应数据包发送回服务器B

  4. 服务器B收到来自服务器A的数据包响应,并将其发送回客户端。

到目前为止,它工作正常。但是,存在一个主要问题。异步循环每个客户端数据包只能从服务器A(源服务器)接收一个数据包。因此,如果服务器B向服务器A发送一个数据包,则服务器B将仅能从服务器A接收一个响应数据包,即使服务器A希望使用多个数据包进行响应。我相信读取功能正在阻止。

我有几个文件。我正在运行此循环中的所有内容:

import asyncio
asyncio.run(server.loop())

然后这是实际的循环(它是一个更长的文件,但是我删除了多余的信息):

    async def loop(self):
        self.server = await asyncio.start_server(self.init, self.settings['proxy']['host'], self.settings['proxy']['ports'][self.type])

        async with self.server:
            print("~Listening @ {%s:%s}" % (self.settings['proxy']['host'], str(self.settings['proxy']['ports'][self.type])))
            print()
            await self.server.start_serving()
            await self.server.serve_forever()

    async def init(self, r, w):
        await cli.client(self, r, w).connect()

如您所见,它调用一个客户端类,该客户端类包含实际代理文件的循环。它从客户端接收数据包,将其发送到服务器A,接收服务器A的响应,然后将其发送回客户端。这是客户端类(已删除冗余信息)

    async def connect(self):
        self.ip = self.w.get_extra_info('peername')
        self.tag = ("[%s:%s]" % (self.ip[0], str(self.ip[1])))
        self.dest['r'], self.dest['w'] = await asyncio.open_connection(host=self.host, port=self.port)

        print("NEW_CLIENT::%s" % (self.tag))

        while(not self.w.is_closing()):
            try:
                data = await self.r.readuntil(separator=b'\x00')
                if data:
                    await self.forward(data)
                else:
                    await self.disconnect()
            except asyncio.IncompleteReadError:
                await self.disconnect()

    async def forward(self, data):
        #data = data.decode("utf-8")[:-1]
        print("<= SEND_DEST::%s %s" % (self.tag, data.decode("utf-8")[:-1]))
        self.dest['w'].write(data)
        await self.dest['w'].drain()
        data = await self.dest['r'].readuntil(separator=b'\x00')
        print("=> RECV_DEST::%s => %s" % (self.tag, data.decode("utf-8")[:-1]))
        if data:
            self.w.write(data)

    async def disconnect(self):
        print("[Disconnect Client]: %s:%s" % (self.ip[0], str(self.ip[1])))
        self.w.close()

到目前为止,一切都按预期进行。客户端将数据包发送到此代理文件(服务器B),该数据包发送到主源(服务器A),主源将数据包发送回代理文件(服务器B),最后服务器B发送服务器A的回复给客户。这是一个有效的代理脚本。

问题:使用此反向代理,我一次只能从主服务器A接收一行。因此,基本上,如果客户端向服务器B发送1个数据包,则此远程代理仅读取来自服务器A的1个响应数据包,即使服务器A发回了多个响应数据包也是如此。因此,基本上,我只能在forward()函数中一次读取一行。

我真的不知道该怎么做,除了可能使阅读过程又循环一遍?我不知道该怎么办。也许使用run_in_executor

0 个答案:

没有答案