首页 > 解决方案 > ConnectionResetError('连接丢失')python异步服务器

问题描述

我正在为连接在端口 9000 上的 redis 客户端编写一个 redis 服务器(使用 redis-py)。

我现在写了一个简单的测试代码来检查服务器是否正在接收客户端的命令。我的代码如下:

客户端.py

import redis

r = redis.Redis(
    host="127.0.0.1",
    port=9000
)

v = r.set('foo', 1)
print(v)

v = r.set('bar', '1')

服务器.py

import asyncio

HOST = "127.0.0.1"
PORT = 15000


async def exo_redis(reader, writer):

    try:
        while True:
            data = await reader.readuntil(b'\r\n')
            # data = await reader.read(1024)
            if not data:
                break
            print("Data: ", data)
            response = "+OK\r\n"
            writer.write(response.encode())
            await writer.drain()

        writer.close()

    except asyncio.streams.IncompleteReadError:
        pass


def start_server():
    loop = asyncio.get_event_loop()
    coro = asyncio.start_server(exo_redis, HOST, PORT)
    server = loop.run_until_complete(coro)
    print("Serving on ", HOST, "port: ", PORT)
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        print("\nShutting Down Server...\n")
    finally:
        server.close()
        loop.run_until_complete(server.wait_closed())
        loop.close()


if __name__ == '__main__':
    start_server()

运行此程序后,我得到的输出有以下异常:

Data:  b'*3\r\n'
Data:  b'$3\r\n'
Data:  b'SET\r\n'
Data:  b'$3\r\n'
Data:  b'foo\r\n'
Task exception was never retrieved
future: <Task finished coro=<exo_redis() done, defined at app.py:13> exception=ConnectionResetError('Connection lost')>
Traceback (most recent call last):
  File "app.py", line 23, in exo_redis
    await writer.drain()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 348, in drain
    await self._protocol._drain_helper()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/streams.py", line 202, in _drain_helper
    raise ConnectionResetError('Connection lost')
ConnectionResetError: Connection lost
Data:  b'*3\r\n'
Data:  b'$3\r\n'
Data:  b'SET\r\n'
Data:  b'$3\r\n'
Data:  b'bar\r\n'
Data:  b'$1\r\n'
Data:  b'1\r\n'

出于某种原因,从客户端发送的第一个命令会引发异常,但第二个不会。

如果我使用 reader.read(1024) (在代码中注释),我会得到以下输出:

Data:  b'*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$1\r\n1\r\n'
Data:  b'*3\r\n$3\r\nSET\r\n$3\r\nbar\r\n$1\r\n1\r\n'

这有时有效并且没有抛出异常,但有时我在命令未完全读取的情况下收到此异常。关于如何纠正这个问题的任何想法,我可以确保在服务器端接收到整个命令?

标签: python-asynciopython-3.7redis-py

解决方案


推荐阅读