Python中asyncio socket的接收问题如何解决?

我使用官方 tutourial 的 18.5.5.7.2. TCP echo server using streams url 是 https://docs.python.org/3/library/asyncio-protocol.html

然后发送一堆 4 个 json 数据,但是这个 tutourial 只能无限循环第一个,这是为什么呢?

接收结果: {"duration": 6909, "timestamp": 1508925087312791, "annotations": [{"host": null, "value": "GET", "key": "http.method", "annotation_type": 6}, {"host": null, "value": "http://localhost:8081/format", "key": "http.url", "annotation_type": 6}], "name": "formatString", "parent_id": 2405405279606511970}{"duration": 5586, "timestamp": 1508925087320016, "annotations": [{"host": null, "value": "GET", "key": "http.method", "annotation_type": 6}, {"host": null, "value": "http://localhost:8082/publish", "key": "http.url", "annotation_type": 6}], "name": "printHello", "parent_id": 2405405279606511970}{"duration": 13221, "timestamp": 1508925087312715, "annotations": [{"host": null, "value": "const", "key": "sampler.type", "annotation_type": 6}, {"host": null, "value": "True", "key": "sampler.param", "annotation_type": 6}, {"host": null, "value": "Python-3.6.1", "key": "jaeger.version", "annotation_type": 6}, {"host": null, "value": "workvm", "key": "jaeger.hostname", "annotation_type": 6},

发送的数据为: {'duration': 6909, 'timestamp': 1508925087312791, 'annotations': [{'host': None, 'value': 'GET', 'key': u'http.method', 'annotation_type': 6}, {'host': None, 'value': 'http://localhost:8081/format', 'key': u'http.url', 'annotation_type': 6}], 'name': u'formatString', 'parent_id': 2405405279606511970}

{'duration': 5586, 'timestamp': 1508925087320016, 'name': u'printHello', 'parent_id': 2405405279606511970, 'annotations': [{'host': None, 'key': u'http.method', 'value': 'GET', 'annotation_type': 6}, {'host': None, 'key': u'http.url', 'value': 'http://localhost:8082/publish', 'annotation_type': 6}]}

{'duration': 13221, 'timestamp': 1508925087312715, 'name': u'say-hello', 'parent_id': None, 'annotations': [{'host': None, 'key': u'sampler.type', 'value': 'const', 'annotation_type': 6}, {'host': None, 'key': u'sampler.param', 'value': 'True', 'annotation_type': 6}, {'host': None, 'key': u'jaeger.version', 'value': 'Python-3.6.1', 'annotation_type': 6}, {'host': None, 'key': u'jaeger.hostname', 'value': 'workvm', 'annotation_type': 6}, {'host': None, 'key': u'hello-to', 'value': 'yyy123', 'annotation_type': 6}]}

{


Python中asyncio socket的接收问题如何解决?

1 回复

在Python的asyncio中处理socket接收,核心是使用loop.sock_recv()loop.sock_recv_into()来执行非阻塞接收。这里给你一个完整的客户端和服务端示例。

服务端代码

import asyncio

async def handle_client(reader, writer):
    while True:
        data = await reader.read(1024)  # 异步读取数据
        if not data:
            break
        message = data.decode()
        print(f"收到消息: {message}")
        writer.write(f"已收到: {message}".encode())
        await writer.drain()  # 确保数据发送完成
    writer.close()

async def main():
    server = await asyncio.start_server(handle_client, '127.0.0.1', 8888)
    async with server:
        await server.serve_forever()

asyncio.run(main())

客户端代码

import asyncio

async def tcp_client():
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
    
    # 发送数据
    writer.write(b"Hello Server!")
    await writer.drain()
    
    # 接收数据
    data = await reader.read(1024)
    print(f"收到回复: {data.decode()}")
    
    writer.close()
    await writer.wait_closed()

asyncio.run(tcp_client())

关键点

  1. 使用asyncio.start_server()asyncio.open_connection()来创建异步socket连接
  2. reader.read()writer.write()是异步操作,需要配合await使用
  3. writer.drain()确保缓冲区数据完全发送
  4. 使用asyncio.run()来运行主协程

如果你需要直接操作底层socket,可以使用loop.sock_recv(sock, maxsize),但通常推荐使用高层级的Stream API(如示例所示),因为它更简洁且不易出错。

总结:优先使用asyncio的Stream API而不是直接操作socket。

回到顶部