了解python套接字中的异步等待io / aiohttp服务器

时间:2018-01-12 15:47:13

标签: python python-3.x asynchronous socket.io python-asyncio

我正在尝试使用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

但是,如果我在代码中取消注释等待休眠的行,我只收到第一条消息:

  

已连接:816fb6700f5143f7875b20a252c65f33

     

消息嘿1

     等等嘿1

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

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

1 个答案:

答案 0 :(得分:5)

我是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中引入的变化导致这些消息在任务休眠时到达而被丢弃,但尚未找到原因。