首页 文章

使用python asyncio从套接字读取时如何避免阻塞?

提问于
浏览
2

我_473220_m试图连接到redis,发送一些命令并读取响应,这可能属于通用的"read a stream of data from some source" . 我无法解决的问题是如何以块的形式读取数据,因为服务器和客户端之间的连接没有被关闭,并且可以多次满足终止序列 \r\n . 如果我等待没有更多数据当然,呼叫将阻止,直到收到其他内容 .

class Client:
    def __init__(self, loop, host='127.0.0.1', port=6379):
        self.host = host
        self.port = port
        self.reader = None
        self.writer = None
        self.loop = loop

    @asyncio.coroutine
    def _connect(self):
        self.reader, self.writer = yield from asyncio.open_connection(
            self.host, self.port, loop=self.loop)

    async def read(self, b=4096):
        resp = b''
        while True:
            chunk = await self.reader.read(b)
            if chunk:
                resp += chunk
            else:
                break
        return resp

让我假装我想以2个字节的块来读取响应(是的是愚蠢的,但它只是为了这个学习目的)所以:

loop = asyncio.get_event_loop()
client = Client(loop)
..... sends some commands here ....
resp = await client.read(2)

我无法弄清楚如果不知道服务器响应的长度,当响应长于从套接字读取的字节时代码仍然是安全的 .

1 回答

  • 0

    我最近遇到了类似的问题 . 我的解决方案是继续阅读,直到读取给定的字符(或一组字符) . 这就是人们说完对讲机后对人们说“结束”的理念 . 等待响应说它已完成说话更容易 .

    虽然之前我没有使用asyncio模块,但我相信下面的代码应该可以解决您的问题,假设输入源以变量 end_signal 中指示的任何字符(或字符串)结束响应 .

    class Client:
        def __init__(self, loop, host='127.0.0.1', port=6379):
            self.host = host
            self.port = port
            self.reader = None
            self.writer = None
            self.loop = loop
    
        @asyncio.coroutine
        def _connect(self):
            self.reader, self.writer = yield from asyncio.open_connection(
                self.host, self.port, loop=self.loop)
    
        async def read(self, b=4096, end_signal = "10101101110111110"):
            resp = b''
            while True:
                chunk = await self.reader.read(b)
                resp += chunk
                if resp[-1*len(end_signal):] == end_signal:
                    break
            return resp
    

相关问题