websocket-python服务端
通过 socket.io 来操作 websocket API。
安装
1 | pip install python-socketio |
创建服务
创建服务的方式
1. 通过 WSGI 托管服务
1 | import socketio |
2. 作为 Django、Flask 应用中的一部分
1 | from wsgi import app # a Flask, Django, etc. application |
不过,现在 django 或 flask 框架都有与之对应的 socket.io 扩展,直接使用即可。
3. 使用 eventlet 运行服务
1 | import eventlet |
解决跨域
由于安全原因,socket.io 采用了同源策略,因此需要解决跨域的问题。
很简单,只需在创建服务的时候添加:
1 | sio = socketio.Server(async_mode='eventlet', cors_allowed_origins='*') |
消息收发
事件
Socket.IO 协议是基于事件的。 当客户端想要与服务器通信时,它会发出一个事件。 每个事件都有一个名称和一个参数列表。 服务器使用 socketio.Server.event() 或 socketio.Server.on() 装饰器注册事件处理函数:
事件处理函数类似于 flask/django 中的视图函数,只不过不是通过 url 来调用对应的方法,而是通过事件名称来调用。
监听事件
监听事件用来接收消息。
1 |
|
被 @sio.event
修饰的函数的名称是事件名,@sio.on
修饰函数的参数是事件名称,该名称与客户端发送消息时使用的事件名称一致。
注意:‘connect’,’disconnect’,’message’ 是特殊的事件,当连接成功,连接失败,接收到消失时会自动调用,除非你想自定义它们的内部代码逻辑,否则应避免用它们作为事件名。
事件处理函数参数介绍:
- sid:session_id,是客户端的身份标识。
- data:客户端发送过来的数据,数据类型与客户端发送的数据类型一致。
提交事件
我们可以向客户端发送事件,从而将一些数据传递到客户端。
1 | sio.emit('hello', {'data': 'hello world'}) |
第一个参数是事件名,第二个参数是数据载荷,他可以接受的类型有 str
,bytes
, list
,,dict
或者 tuple
。
命名空间
Socket.IO 协议支持多个逻辑连接,全部复用在同一个物理连接上。 客户端可以通过在每个连接上指定不同的命名空间来打开多个连接。 命名空间由客户端作为主机名和端口之后的路径名给出。 例如,连接到 http://localhost:8000/chat 将打开到命名空间 /chat 的连接。
每个命名空间都独立于其他命名空间进行处理,具有单独的会话 ID (sids)、事件处理程序和房间。
1 |
|
客户端代码:
1 | import {io} from 'socket.io-client'; |
房间
为了方便服务器向相关客户端组发送事件,应用程序可以将其客户端放入“房间”,然后将消息发送到这些房间。
socketio.SocketIO.emit() 方法的 room 参数用于将特定客户端指定为事件的接收者。 这是因为在连接时,会为每个客户端创建一个个人房间,并使用分配给连接的 sid 命名。 然后应用程序可以自由地创建额外的房间并使用 socketio.Server.enter_room() 和 socketio.Server.leave_room() 方法管理其中的客户端。 客户可以根据需要在多个房间中,并且可以根据需要经常在房间之间移动。
1 |
|
如果我们想要向一个房间中的所有连接发送消息,可以这样做:
1 |
|
skip_sid
指明不向某个连接发送消息。这也是 scoket.io 的广播机制。
1 | // 返回该连接所在房间的列表 |
更多内容请看 python-socketio。
flask 中使用 socketio
安装
1 | pip install flask_socketio |
配置
webapp/init.py
1 | from flask_socketio import SocketIO |
app.py
1 | from webapp import createApp, sio |
这里只是将 app.run()
改为 sio.run()
,不影响其启动和运行。
注意:
development server 启用不了 eventlet,传输协议只能是 polling 而不是 websocket。因此,在开发期间去掉 async_mode 参数,在部署时配合 gunicorn 即可使用 eventlet。
socketio 默认单个消息最大数据量为 1M,需要通过 max_http_buffer_size 参数将此限制放宽。
详细内容请见:https://flask-socketio.readthedocs.io/en/latest/deployment.html。