Asyncio StreamReader 偶尔读取 0 字节

问题描述 投票:0回答:1

我有一个简单的流读取器,它正在监听 TCP 端口以实现 Websocket。该流偶尔会读取(每 30-300 秒)空白数据并引发错误。

loop = asyncio.get_event_loop()
coro = asyncio.start_server(handle_echo, 'not.real.ip.address', 8888, loop=loop)
server = loop.run_until_complete(coro)

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

@asyncio.coroutine
def handle_echo(reader, writer):
    #Starts the connection with upgrade handshake

    while True:
        #read frame data
        first_byte = yield from reader.readexactly(1)
        opcode = first_byte & 0xf

        second_byte = yield from reader.readexactly(1)
        second_byte = ord(second_byte)
        mask = second_byte >> 7
        len1 = second_byte & 0x7f

        if len1 == 126: 
            len2 = yield from reader.readexactly(2)
            length = int.from_bytes(len2, byteorder='big')
        elif len1 == 127:
            len2 = yield from reader.readexactly(8)
            length = int.from_bytes(len2, byteorder='big')
        else:
            length = len1

        if mask:
            masking_key = yield from reader.readexactly(4)

        if length:
            payload = yield from reader.readexactly(length)
            payload = bytearray(payload)
            if mask:
                for i,b in enumerate(payload):
                    payload[i] = payload[i] ^ masking_key[i%4]

        if opcode & 0x1:
            payload = payload.decode("UTF-8")

每隔一段时间,就会抛出以下错误:

Future/Task exception was never retrieved
future: Task(<handle_echo>)<exception=IncompleteReadError('0 bytes read on a total of 1 expected bytes',)>
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/tasks.py", line 300, in _step
    result = coro.send(value)
  File "server.py", line 76, in handle_echo
    first_byte = yield from reader.readexactly(1)
  File "/usr/lib/python3.4/asyncio/streams.py", line 464, in readexactly
    raise IncompleteReadError(partial, len(partial) + n)
asyncio.streams.IncompleteReadError: 0 bytes read on a total of 1 expected bytes

我很难找出造成这种情况的原因。我已经使用 tcptrack 来监视端口,但什么也没有通过。我是否不正确地从端口读取数据,是否需要进行某种清理,或者读者偶尔会误读?我尝试过其他读取函数(read 和 readline),它们偶尔会抛出类似的错误。

python-3.x python-asyncio
1个回答
0
投票

readexactly()
是一种挑剔的方法。 来自文档:

准确读取 n 个字节。如果在读取 n 之前到达流末尾,则引发

IncompleteReadError
,异常的
IncompleteReadError.partial
属性包含部分读取的字节。

由于服务器有时似乎会发送空字节字符串,因此将

readexactly()
调用放在 try / except 块上可能是个好主意:

try:
    first_byte = yield from reader.readexactly(1)
except asyncio.IncompleteReadError:
    pass
else:
    # Rest of your code

您甚至可以检查是否收到了超过 0(零)字节并缓冲它们(如果您的用例需要):

except asyncio.IncompleteReadError as e:
    if len(e.partial) > 0:
        # Handle the bytes read
    else:
        pass
© www.soinside.com 2019 - 2024. All rights reserved.