python-socketio 文档翻译

教程:https://tutorialedge.net/python/python-socket-io-tutorial/

python-socketio 原文地址 ,在google浏览器中可以翻译为中文去使用。

首先要搞明白几个问题:

room – The recipient of the message. This can be set to the session ID of a client to address that client’s room, or to any custom room created by the application, If this argument is omitted the event is broadcasted to all connected clients.

说明
1)第一种room是每一个单独的客户端都有的。(通过session ID可以找到)
2)第二种是应用程序自己创建的。
在下面这个方法中,如果省略掉room参数,将会自动发送给所有的连接了的客户端。

send`(*data*, *room=None*, *skip_sid=None*, *namespace=None*, *callback=None*, ***kwargs*)[¶](https://python-socketio.readthedocs.io/en/latest/#socketio.Server.send "Permalink to this definition")

译文:

Python-socketio实现了一个Python Socket.IO 服务,这个服务可以单独运行也可以综合于一个web项目中。下面是一些它的特征:

1. 对于javascript,Swift,C++,Java以及官方的Socket.IO 客户端都兼容,以及兼容任何遵循Socket.IO准则的三方客户端。
2.Python2.7, Python3.3+ 都是支持的非常好。
3.支持非常多的客户端,甚至是流行的硬件,当使用基于 [asyncio](https://docs.python.org/3/library/asyncio.html) ([sanic](http://sanic.readthedocs.io/) and [aiohttp](http://aiohttp.readthedocs.io/)), [eventlet](http://eventlet.net/) or [gevent](http://gevent.org/).
的异步服务器。在开发和测试中,任意的 `WSGI` 兼容的多线程服务器都可以使用。
4.内置了一个WSGI中间件去结合Socket.IO流量和标准WSGI应用。
5.广播消息通知所有连接的客户端,或者分配它们到“房间”。
6.多个服务器是可选支持的,通过messaging queue,比如Redis或者RabbitMQ。
7.可以通过外部的流程去发消息给客户端,比如Celery workers或者辅助的脚本。
8.基于事件的带有修饰器的架构去隐藏这个协议的一些细节。
9.支持HTTP长轮询和WebSocket传输协议。
10.支持XHR2和XHR浏览器。
11.支持文本和二进制消息。
12.支持gzip和HTTP压缩。
13.可配置的CORS响应,避免在浏览器上出现跨域问题。

什么是Socket.IO?

Socket.IO是一个基于事件的双向通讯的传输协议(一般是web浏览器),和一个服务端。原始的客户端和服务端组件实现是通过JavaScript写的。

入门指南

可以使用pip安装Socket.IO:

pip install python-socketio

下面是一个使用aiohttp框架(只支持Python 3.5+)实现异步IO的 Socket.IO server 简单的例子:

from aiohttp import web
import socketio

sio = socketio.AsyncServer()
app = web.Application()
sio.attach(app)

async def index(request):
    """Serve the client-side application."""
    with open('index.html') as f:
        return web.Response(text=f.read(), content_type='text/html')

@sio.on('connect', namespace='/chat')
def connect(sid, environ):
    print("connect ", sid)

@sio.on('chat message', namespace='/chat')
async def message(sid, data):
    print("message ", data)
    await sio.emit('reply', room=sid)

@sio.on('disconnect', namespace='/chat')
def disconnect(sid):
    print('disconnect ', sid)

app.router.add_static('/static', 'static')
app.router.add_get('/', index)

if __name__ == '__main__':
    web.run_app(app)

下面是一个类似的例子,但是使用的Flask和Eventlet的例子,兼容Python2.7和3.3+:

import socketio
import eventlet
from flask import Flask, render_template

sio = socketio.Server()
app = Flask(__name__)

@app.route('/')
def index():
    """Serve the client-side application."""
    return render_template('index.html')

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

@sio.on('my message')
def message(sid, data):
    print('message ', data)

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

if __name__ == '__main__':
    # wrap Flask application with socketio's middleware
    app = socketio.Middleware(sio, app)

    # deploy as an eventlet WSGI server
    eventlet.wsgi.server(eventlet.listen(('', 8000)), app)

客户端应用必须引入 socket.io-client 库(1.3.5版本以及以上,越高越好)。

每次客户端连接到服务器的连接事件处理程序调用sid(会话ID)分配给连接和WSGI环境字典。

每次客户端连接到服务端的 conenct 事件都是由sid(session ID)分配到连接和WSGI环境字典调用的。服务端可以检查身份认证或者其他的头部信息去决定是否这个客户端允许被连接。要想拒绝一个客户端的连接,这个处理器必须返回 False

当客户端发送发送一个事件给服务端,相应的事件处理器会被sid和这个信息调用,可以是单个或者多个参数。这个应用可以定义尽量多的如果被需要的可以被事件处理器关联的事件。一个事件可以通过一个名称简单定义。

当一个客户端连接中断了,disconnect 事件就被调用,允许应用去执行清理工作。

服务端

Socket.IO 服务端是 socketio.Server 类的实例,他们可以被一个WSGI适用应用程序使用 socketio.Middleware 去合并:

# create a Socket.IO server
sio = socketio.Server()

# wrap WSGI application with socketio's middleware
app = socketio.Middleware(sio, app)

使用 socketio.Server.on() 方法来注册服务端的事件处理器:

@sio.on('my custom event')
def my_custom_event():
    pass

对于异步服务端来说,事件处理器可以是常规方法,或者是协程:

@sio.on('my custom event')
async def my_custom_event():
    await sio.emit('my reply')

聊天室

因为Socket.IO是一个双向的协议,服务端可以在任意时间发送消息给任意的连接到的客户端。为了让它方便去将客户端定位到组中,应用程序可以将客户端放入到聊天室中去,然后将消息定位到整个聊天室中。

当客户端第一次连接,他们是被分配到他们自己的聊天室中,这个聊天是是以session ID(sid 参数会传递给所有的事件处理器)命名的。应用可以通过 socketio.Server.enter_room()socketio.Server.leave_room() 自由地去创建聊天室和管理客户端。客户端可以在尽量多的房间里,也可以根据需求尽量频繁地被拉入拉出聊天室。当他们的连接不在特别的时候,单独的聊天室将会分配给她它们,应用程序可以自由地增加和移除客户端从聊天室中,尽管它只要这样做就会失去定位独立客户端的能力。

@sio.on('enter room')
def enter_room(sid, data):
    sio.enter_room(sid, data['room'])

@sio.on('leave room')
def leave_room(sid, data):
    sio.leave_room(sid, data['room'])

socketio.Server.emit() 方法会获得一个事件名称,一个可能是 strbyteslistdict 或者 tuple 类型的消息载体。当发送一个 tuple,在其中的元素必须是上面的其他类型。元组中的元素将会被传递给客户端的回调函数为多个参数。定位一个个人客户端,客户端的sid将会被给一个聊天室(假设这个应用没有修改这些初始的聊天室)。定位所有的连接的客户端们,这个聊天室参数将会被触发。

@sio.on('my message')
def message(sid, data):
    print('message ', data)
    sio.emit('my reply', data, room='my room')

通常在聊天室中当广播一个消息到一个用户组的时候,发送者是否接受他自己的消息是可选的。soicketio.Server.emit() 方法提供了一个可选的 skip_sid 参数去指定一个想在广播中跳过的客户端。

@sio.on('my message')
def message(sid, data):
    print('message ', data)
    sio.emit('my reply', data, room='my room', skip_sid=sid)

Response

当一个客户端发送一个事件给服务端,它可以选择提供一个回调方法,当服务端返回一个响应的时候会被触发。服务端可以便捷地从相应的事件处理器返回它从而提供一个响应。

@sio.on('my event', namespace='/chat')
def my_event_handler(sid, data):
    # handle the message
    return "OK", 123

事件处理器可以返回一个单独的值,一个带多个值的元组。这个在客户端的回调函数将会调用这些返回的值。

Callbacks
回调

服务端可以请求一个响应通过发送一个事件给客户端。socketio.Server.emit() 方法有一个可选的 callback 参数能够被设置为可回调的。当这个参数被传递之后,当客户端返回相应的时候,这个可回调的方法将会被请求。

当广播给多个客户端的时候使用回调函数是不被推荐的,因为回调方法将会被只执行一次。

Namespace
命名空间

Socket.IO 协议支持多个逻辑性连接,所有的多路复用都是在相同的物理连接上。客户端可以通过给每个连接指定不同的 namespace 从而开多个连接。一个命名空间是由 主机名+端口+路径名称构成的。比如,连接到 http://example.com:8000/chat 将会开一个连接到命名空间 /chat

由于分离的不同的session ID(sids),不同的事件处理器,不同的聊天室,每一个命名空间都是独立的。应用程序使用多个命名空间从而来区分命名空间,是非常重要的。可以参考 socketio.Server 类。

namespace 参数被触发了,比如设置为 None 或者 /, 那么一个默认的命名空间将会被使用。

Class-Based Namespaces

作为一个基于装饰器的事件处理器的代替,这个属于一个命名空间事件处理器可以被创建为 socketio.Namesapce 的子类:

class MyCustomNamespace(socketio.Namespace):
    def on_connect(self, sid, environ):
        pass

    def on_disconnect(self, sid):
        pass

    def on_my_event(self, sid, data):
        self.emit('my_response', data)

sio.register_namespace(MyCustomNamespace('/test'))

对于基于异步io的服务端,域名空间必须继承与 socketio.AsyncNamespace, 也可以定义普通的方法或者协程作为事件处理器:

class MyCustomNamespace(socketio.AsyncNamespace):
    def on_connect(self, sid, environ):
        pass

    def on_disconnect(self, sid):
        pass

    async def on_my_event(self, sid, data):
        await self.emit('my_response', data)

sio.register_namespace(MyCustomNamespace('/test'))

当使用基于类的命名空间的时候,任何被服务端接受的事件将会被分派到一个被事件名称命名的方法中作为方法名称(with the on_pfrefix)。比如:事件 my_event 将会被一个名叫 on_my_event 的方法处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349