我正在尝试开发一种“反向代理”类型的东西,并且我差不多完成了。但是,我遇到了一个问题。我有两台服务器。运行实际源的主服务器(服务器A)和客户端将连接到的代理服务器(服务器B)。
基本上,我的设计如下:
客户端连接到服务器B(代理服务器)后...
客户端开始将其数据包发送到服务器B。
服务器B将其数据包发送到服务器A
服务器A接收到它们的数据包,对其进行适当的解析(这是实际的来源),然后将响应数据包发送回服务器B
服务器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
?