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的接收问题如何解决?
在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())
关键点:
- 使用
asyncio.start_server()和asyncio.open_connection()来创建异步socket连接 reader.read()和writer.write()是异步操作,需要配合await使用writer.drain()确保缓冲区数据完全发送- 使用
asyncio.run()来运行主协程
如果你需要直接操作底层socket,可以使用loop.sock_recv(sock, maxsize),但通常推荐使用高层级的Stream API(如示例所示),因为它更简洁且不易出错。
总结:优先使用asyncio的Stream API而不是直接操作socket。

