Socket.IO 服务器
此软件包包含两个 Socket.IO 服务器:
socketio.Server()
类可创建与 Python 标准库兼容的服务器。
socketio.AsyncServer()
类可创建与 asyncio
软件包兼容的服务器。
这两个服务器中的方法相同,唯一的区别在于,asyncio
服务器中的大多数方法是以协程形式实现的。
安装
若要安装 Socket.IO 服务器及其依赖项,可使用以下命令:
pip install python-socketio
若你打算基于 asyncio
软件包构建异步 Web 服务器,可使用以下命令安装此软件包及所需的其他依赖项:
pip install "python-socketio[asyncio]"
创建服务器实例
Socket.IO 服务器是 socketio.Server
类的一个实例:
import socketio
# 创建一个 Socket.IO 服务器
sio = socketio.Server()
对于基于 asyncio
的服务器,socketio.AsyncServer
类提供了相同的功能,但采用了更适合协程的格式:
import socketio
# 创建一个 Socket.IO 服务器
sio = socketio.AsyncServer()
运行服务器
要运行 Socket.IO 应用程序,需要配置一个 Web 服务器,以接收来自客户端的传入请求,并将其转发给 Socket.IO 服务器实例。为简化此任务,有多种集成方式可供选择,其中包括对 WSGI 和 ASGI 标准的支持。

作为 WSGI 应用程序运行
若要将 Socket.IO 服务器配置为 WSGI 应用程序,可使用 socketio.WSGIApp
类包装服务器实例:
# 用 WSGI 应用程序包装
app = socketio.WSGIApp(sio)
生成的 WSGI 应用程序可使用支持 WSGI 的服务器来执行,例如开发环境中使用的 Werkzeug 和生产环境中使用的 Gunicorn。
当将 Socket.IO 与使用 Flask 或 Django 等 WSGI 框架编写的 Web 应用程序结合使用时,WSGIApp
类可将两个应用程序包装在一起,并将流量路由到它们:
from mywebapp import app # 一个 Flask、Django 等应用程序
app = socketio.WSGIApp(sio, app)
作为 ASGI 应用程序运行
若要将 Socket.IO 服务器配置为 ASGI 应用程序,可使用 socketio.ASGIApp
类包装服务器实例:
# 用 ASGI 应用程序包装
app = socketio.ASGIApp(sio)
生成的 ASGI 应用程序可使用符合 ASGI 标准的 Web 服务器来执行,例如 Uvicorn。
Socket.IO 还可与使用 FastAPI 等 ASGI Web 框架编写的 Web 应用程序结合使用。在这种情况下,ASGIApp
类可将两个应用程序包装在一起,并将流量路由到它们:
from mywebapp import app # 一个 FastAPI 或其他 ASGI 应用程序
app = socketio.ASGIApp(sio, app)
提供静态文件
可以将 Socket.IO 服务器配置为向客户端提供静态文件。当此软件包在没有配套 Web 框架的情况下使用时,这对于向客户端交付 HTML、CSS 和 JavaScript 文件特别有用。
静态文件通过一个 Python 字典进行配置,其中每个键值对都是一个静态文件映射规则。最简单的形式是,这个字典以一个或多个静态文件的 URL 作为键,以服务器中对应的文件作为值:
static_files = {
'/': 'latency.html',
'/static/socket.io.js': 'static/socket.io.js',
'/static/style.css': 'static/style.css',
}
通过此示例配置,当服务器收到对 /
(根 URL)的请求时,它将返回当前目录中 latency.html
文件的内容,并根据文件扩展名分配内容类型,在这种情况下为 text/html
。
扩展名为 .html
、.css
、.js
、.json
、.jpg
、.png
、.gif
和 .txt
的文件会被自动识别并分配正确的内容类型。对于其他扩展名或无扩展名的文件,默认使用 application/octet-stream
作为内容类型。
如果需要,可为静态文件指定显式的内容类型,如下所示:
static_files = {
'/': {'filename': 'latency.html', 'content_type': 'text/plain'},
}
也可以在一个规则中配置整个目录,以便将其中的所有文件作为静态文件提供:
static_files = {
'/static': './public',
}
在此示例中,任何以 /static
开头的 URL 请求的文件都将直接从当前目录的 public
文件夹中提供。例如,URL /static/index.html
将返回本地文件 ./public/index.html
,URL /static/css/styles.css
将返回本地文件 ./public/css/styles.css
。
如果请求的 URL 以 /
结尾,则会自动在其后追加默认文件名 index.html
。在前面的示例中,对 /static/
URL 的请求将返回本地文件 ./public/index.html
。对于以斜杠结尾的 URL 要提供的默认文件名,可以在静态文件字典中使用空键进行设置:
static_files = {
'/static': './public',
'': 'image.gif',
}
通过此配置,对 /static/
的请求将返回本地文件 ./public/image.gif
。如有需要,也可以指定非标准的内容类型:
static_files = {
'/static': './public',
'': {'filename': 'image.gif', 'content_type': 'text/plain'},
}
静态文件配置字典作为 static_files
参数传递给 socketio.WSGIApp
或 socketio.ASGIApp
类:
# 对于标准的 WSGI 应用程序
sio = socketio.Server()
app = socketio.WSGIApp(sio, static_files=static_files)
# 对于基于 asyncio 的 ASGI 应用程序
sio = socketio.AsyncServer()
app = socketio.ASGIApp(sio, static_files=static_files)
这两个类中的路由优先级如下:
- 首先,检查路径是否与 Socket.IO 端点匹配。
- 接着,若存在静态文件配置,则检查路径是否与之匹配。
- 若路径与 Socket.IO 端点或任何静态文件均不匹配,且配置了二级应用程序,则将控制权传递给该应用程序;否则返回 404 错误。
注意:静态文件服务仅用于开发环境,因此缺少缓存等重要功能,请勿在生产环境中使用。
事件
Socket.IO 协议基于事件当客户端想与服务器通信,或者服务器想与一个或多个客户端通信时,它们会向对方发送一个事件。每个事件都有一个名称,还可以有一个可选的参数列表。
监听事件
为了接收来自客户端的事件,服务器应用程序必须注册事件处理函数。当客户端发出相应事件时,这些函数会被调用。要为某个事件注册处理函数,可使用 socketio.Server.event()
或 socketio.Server.on()
装饰器:
@sio.event
def my_event(sid, data):
pass
@sio.on('my custom event')
def another_event(sid, data):
pass
在第一个例子中,事件名称是从处理函数的名称获取的。第二个例子稍微详细一些,但它允许事件名称与函数名称不同,或者包含函数名称中不合法的字符,例如空格。
对于使用 asyncio
的服务器,事件处理函数可以选择作为协程提供:
@sio.event
async def my_event(sid, data):
pass
传递给所有处理函数的 sid
参数是 Socket.IO 会话 ID,这是 Socket.IO 为每个客户端连接分配的唯一标识符。给定客户端发送的所有事件都将具有相同的 sid
值。
连接和断开连接事件
连接(connect
)和断开连接(disconnect
)事件比较特殊;当客户端连接到服务器或从服务器断开连接时,它们会自动被调用:
@sio.event
def connect(sid, environ, auth):
print('connect ', sid)
@sio.event
def disconnect(sid, reason):
print('disconnect ', sid, reason)
连接事件是执行用户身份验证的理想时机,也是在应用程序中的用户实体和分配给客户端的 sid
之间进行必要映射的好地方。
除了 sid
之外,连接处理函数还会接收 environ
作为参数,其中包含标准 WSGI 格式的请求信息,包括 HTTP 标头。连接处理函数还会接收 auth
参数,其中包含客户端传递的任何身份验证详细信息;如果客户端未传递任何身份验证信息,则为 None
。
在检查参数之后,连接事件处理函数可以返回 False
以拒绝与客户端的连接。有时&#