了解python socket io / aiohttp服务器中的异步等待

Posted

技术标签:

【中文标题】了解python socket io / aiohttp服务器中的异步等待【英文标题】:Understanding async await in python socket io / aiohttp server 【发布时间】:2018-06-22 02:42:07 【问题描述】:

我正在尝试使用python-socketio 设置 socket.io 服务器。 这是一个最小的工作示例:

import asyncio
from aiohttp import web
import socketio
import random

sio = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
sio.attach(app)

@sio.on('connect')
def connect(sid, environ):
    print("connected: ", sid)

@sio.on('sendText')
async def message(sid, data):
    print("message ", data)
    # await asyncio.sleep(1 * random.random())
    # print('waited', data)

@sio.on('disconnect')
def disconnect(sid):
    print('disconnect ', sid)

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=8080)

这运行良好,例如我可以执行(在 node.js 中)

const io = require('socket.io-client');
const socket = io('ws://localhost:8080');
socket.emit('sendText', 'hey 1')
socket.emit('sendText', 'hey 2')
socket.emit('sendText', 'hey 3')

如果我运行服务器并运行上面的节点脚本,我会得到服务器端

已连接:c1e687f0e2724b339fcdbefdb5aaa8f8

发消息嘿1

发消息嘿2

发消息嘿 3

但是,如果我取消注释代码中的 await sleep 行,我只会收到第一条消息:

已连接:816fb6700f5143f7875b20a252c65f33

发消息嘿1

等一下,嘿 1

我不明白为什么没有出现下一条消息。 只能同时运行一个async def message 实例吗?或者为什么?

我确信我不了解它是如何工作的一些非常基本的东西。如果有人能指出我不理解的地方,我将不胜感激。

【问题讨论】:

当您运行睡眠时,它会停止一段时间,因此接收到的任何消息都不会被正确处理。 睡眠的不只是对协程的调用吗? @Jaxi: asyncio.sleep() 确实不会阻塞执行,它专门设计用于将协程放在非活动队列中,直到时间过去。您似乎将此与 time.sleep() 混淆了。 @Julius:宾果游戏。我的aiohttp 相当老了,aiohttp==1.0.2;我们的python-socketio 版本匹配。但是当我将aiohttp 升级到版本 2.3.7 时,我看到了同样的问题。 @Julius:和 2.2.5 没有表现出这种行为,但 2.3.0 。我们正在做一些事情。 【参考方案1】:

我是 python-socketio 包的作者。我认为这里有两个问题。我可以回答你的问题:

只能同时运行一个异步 def 消息实例吗?或者为什么?

我的 Socket.IO 服务器序列化从给定客户端接收到的事件。例如,如果客户端 A 发送一个运行一分钟的事件,那么 A 在该分钟内发送的任何其他事件都将排队,等待第一个事件首先完成。如果客户端 B 在那一分钟内发送了一个事件,它将被立即处理。来自客户端的事件被人为序列化的原因是为了防止由于同一客户端的两个或多个处理程序并行运行而发生竞争条件或其他副作用。可以使用async_handlers 选项关闭这种事件序列化:

sio = socketio.AsyncServer(async_mode='aiohttp', async_handlers=True)

使用 aiohttp 2.3.7 和 async_handlers=True 您的三个事件或多或少同时收到,然后所有处理程序在它们的睡眠期间并行等待。

不幸的是,这并不能解释第二个和第三个事件永远不会到达服务器。我已验证这些事件已正确排队并使用 aiohttp 2.2.5 按顺序执行,但这与 2.3.0 一直中断到 2.3.7。我目前的理论是,2.3.0 中引入的更改导致这些在任务休眠时到达的消息被丢弃,但尚未找到发生这种情况的原因。

【讨论】:

太棒了! async_handlers=True 正是我所需要的,现在它都适用于 aiohttp 2.2.5。感谢一个很棒的图书馆。我希望你设法弄清楚 >2.3.0 的问题。

以上是关于了解python socket io / aiohttp服务器中的异步等待的主要内容,如果未能解决你的问题,请参考以下文章

了解socket.io的文档模式

python socket了解使用

如何使用 python 连接到 socket.io

iOS学习——Socket

《Python》IO模型

Python----Socket编程IO多路复用SocketServer