| FLASK-SOCKETIO(1) | Flask-SocketIO | FLASK-SOCKETIO(1) |
نام (NAME)
flask-socketio - مستندات flask-socketio
بسته Flask-SocketIO به برنامههای کاربردی Flask امکان دسترسی به ارتباطات دوطرفه با تأخیر اندک میان کلاینتها و سرور را فراهم میکند. برنامه کاربردی سمت کلاینت میتواند از هر یک از کتابخانههای کلاینت SocketIO http://socket.io در Javascript، Python، C++، Java و Swift یا هر کلاینت سازگار دیگری برای برقراری یک اتصال پایدار با سرور استفاده کند.
مقدمه (INTRODUCTION)
نصب (Installation)
میتوانید این بسته را به شیوه معمول با استفاده از pip نصب کنید:
pip install flask-socketio
نیازمندیها (Requirements)
بسته Flask-SocketIO با Python 3.8+ سازگار است. سرویسهای ناهمگام (asynchronous) که این بسته به آنها وابسته است را میتوان از میان سه گزینه زیر انتخاب کرد:
- بسته threading از کتابخانه استاندارد Python آسانترین و سازگارترین راهحل است که پشتیبانی کاملی از روشهای انتقال long-polling و WebSocket ارائه میدهد. از وبسرور توسعه Flask میتوان در طول توسعه استفاده کرد و Gunicorn در حالت چندرشتهای (multi-threaded) را میتوان در استقرارهای محیط عملیاتی به کار گرفت.
- ابزار gevent http://www.gevent.org در چندین پیکربندی گوناگون و همچنین با پشتیبانی از روشهای انتقال long-polling و WebSocket پشتیبانی میشود. هنگام استفاده از gevent، وبسرور توسعه Flask، وبسرور اختصاصی gevent، سرور Gunicorn (به همراه ورکر gevent) و uWSGI (در حالت gevent) همگی قابل استفاده هستند.
- ابزار eventlet http://eventlet.net در گذشته گزینه مناسبی با پشتیبانی از روشهای انتقال long-polling و WebSocket بود، اما دیگر بهطور فعال نگهداری نمیشود؛ بنابراین استفاده از gevent در اولویت است. هنگام استفاده از eventlet، وبسرور توسعه Flask، وبسرور اختصاصی eventlet و Gunicorn (به همراه ورکر eventlet) همگی پشتیبانی میشوند.
این افزونه بهطور خودکار بر اساس بستههای نصبشده تشخیص میدهد که از کدام چارچوب ناهمگام استفاده کند. اولویت با eventlet است و پس از آن gevent قرار دارد. در صورتی که هیچیک از بستههای eventlet یا gevent نصب نشده باشند، از بسته threading پایتون استفاده میشود.
در صورت استفاده از چند پردازش، باید یک سرویس صف پیام (message queue) پیکربندی شود تا سرورها بتوانند عملیاتی مانند انتشار همگانی (broadcasting) را هماهنگ کنند. صفهای پشتیبانیشده عبارتند از Redis http://redis.io، RabbitMQ https://www.rabbitmq.com، Kafka http://kafka.apache.org و هر صف پیام دیگری که توسط بسته Kombu http://kombu.readthedocs.org/en/latest پشتیبانی میشود.
در سمت کلاینت، میتوان از کتابخانه رسمی کلاینت Socket.IO در Javascript برای برقراری اتصال به سرور استفاده کرد. همچنین کلاینتهای رسمی نوشتهشده به زبانهای Swift، Java و C++ نیز موجود هستند. کلاینتهای غیررسمی نیز در صورتی که پروتکل Socket.IO https://github.com/socketio/socket.io-protocol را پیادهسازی کرده باشند، بدون مشکل کار خواهند کرد. بسته python-socketio https://github.com/miguelgrinberg/python-socketio (که پیادهسازی سرور Socket.IO مورد استفاده در Flask-SocketIO را فراهم میکند) شامل یک کلاینت پایتون است..SS "سازگاری نسخهها (Version compatibility)"
پروتکل Socket.IO چندین بازنگری را پشت سر گذاشته است و برخی از آنها تغییرات ناسازگار با قبل ایجاد کردهاند؛ این بدان معناست که برای عملکرد درست همه بخشها، کلاینت و سرور باید از نسخههای سازگار استفاده کنند.
جدول سازگاری نسخهها در زیر، نسخههای این بسته را با نسخههای پیادهسازی مرجع JavaScript و نسخههای پروتکلهای Socket.IO و Engine.IO تطبیق میدهد.
| نسخه Socket.IO در JavaScript | بازنگری پروتکل Socket.IO | بازنگری پروتکل Engine.IO | نسخه Flask-SocketIO | نسخه python-socketio | نسخه python-engineio |
| 0.9.x | 1, 2 | 1, 2 | پشتیبانی نمیشود | پشتیبانی نمیشود | پشتیبانی نمیشود |
| 1.x و 2.x | 3, 4 | 3 | 4.x | 4.x | 3.x |
| 3.x و 4.x | 5 | 4 | 5.x | 5.x | 4.x |
شروع به کار (GETTING STARTED)
مقداردهی اولیه (Initialization)
مثال کد زیر نحوه افزودن Flask-SocketIO به یک برنامه Flask را نشان میدهد:
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
if __name__ == '__main__':
socketio.run(app)
شیوه مقداردهی اولیه با الگوی init_app() نیز پشتیبانی میشود:
from flask import Flask, render_template
from flask_socketio import SocketIO
socketio = SocketIO()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio.init_app(app)
return app
if __name__ == '__main__':
app = create_app()
socketio.run(app)
برای راهاندازی وبسرور، کافی است اسکریپت خود را اجرا کنید. به نحوه راهاندازی وبسرور توجه داشته باشید. تابع socketio.run() فرایند راهاندازی وبسرور را کپسولهسازی کرده و جایگزین راهاندازی استاندارد سرور توسعه Flask با app.run() میشود. هنگامی که برنامه در حالت اشکالزدایی (debug) است، سرور توسعه Werkzeug همچنان استفاده شده و درون socketio.run() بهدرستی پیکربندی میشود. در حالت عملیاتی (production)، در صورت در دسترس بودن از وبسرور eventlet استفاده میشود، در غیر این صورت وبسرور gevent به کار گرفته خواهد شد. اگر eventlet و gevent نصب نشده باشند، وبسرور توسعه Werkzeug استفاده میشود.
دستور flask run که در Flask 0.11 معرفی شد، میتواند برای راهاندازی سرور توسعه Flask-SocketIO مبتنی بر Werkzeug به کار رود، اما این روش راهاندازی سرور Flask-SocketIO به دلیل عدم پشتیبانی از WebSocket توصیه نمیشود. نسخههای قبلی این بسته شامل یک نسخه سفارشی از دستور flask run بودند که امکان استفاده از WebSocket را روی سرورهای عملیاتی eventlet و gevent فراهم میکرد، اما این قابلیت به نفع روش راهاندازی socketio.run(app) که در بالا نشان داده شد و پایدارتر است، متوقف شده است.
برنامه باید صفحهای را برای کلاینت سرو کند که کتابخانه Socket.IO را بارگذاری کرده و یک اتصال برقرار نماید:
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on('connect', function() {
socket.emit('my event', {data: 'I\'m connected!'});
});
</script>
هنگام استفاده از SocketIO، پیامها توسط هر دو طرف بهصورت رویداد دریافت میشوند. در سمت کلاینت از کالبکهای JavaScript استفاده میشود. با Flask-SocketIO، سرور باید گردانندههایی (handlers) برای این رویدادها ثبت کند، مشابه روشی که مسیرها توسط توابع view مدیریت میشوند.
مثال زیر یک گردانندهی رویداد سمت سرور را برای یک رویداد بدون نام ایجاد میکند:
@socketio.on('message')
def handle_message(data):
print('received message: ' + data)
مثال بالا از پیامهای رشتهای استفاده میکند. نوع دیگری از رویدادهای بدون نام از دادههای JSON استفاده میکنند:
@socketio.on('json')
def handle_json(json):
print('received json: ' + str(json))
انعطافپذیرترین نوع رویداد از نامهای سفارشی رویداد استفاده میکند. دادههای پیام برای این رویدادها میتوانند string، bytes، int یا JSON باشند:
@socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json))
رویدادهای سفارشی دارای نام همچنین میتوانند از چندین آرگومان پشتیبانی کنند:
@socketio.on('my_event')
def handle_my_custom_event(arg1, arg2, arg3):
print('received args: ' + arg1 + arg2 + arg3)
هنگامی که نام رویداد یک شناسه معتبر در Python باشد و با سایر نمادهای تعریفشده تداخلی نداشته باشد، دکوراتور @socketio.event ساختار فشردهتری را ارائه میدهد که نام رویداد را از تابع تزئینشده (decorated function) میگیرد:
@socketio.event
def my_custom_event(arg1, arg2, arg3):
print('received args: ' + arg1 + arg2 + arg3)
رویدادهای نامگذاریشده بیشترین انعطافپذیری را دارند، زیرا نیاز به درج متادیتای اضافی جهت توصیف نوع پیام را از بین میبرند. نامهای message، json، connect و disconnect رزرو شدهاند و نمیتوان آنها را برای رویدادهای دارای نام استفاده کرد.
همچنین Flask-SocketIO از namespaceهای SocketIO پشتیبانی میکند، که به کلاینت اجازه میدهد چندین اتصال مستقل را روی همان سوکت فیزیکی مالتیپلاکس (multiplex) کند:
@socketio.on('my event', namespace='/test')
def handle_my_custom_namespace_event(json):
print('received json: ' + str(json))
هنگامی که یک namespace مشخص نشده باشد، یک namespace سراسری پیشفرض با نام '/' استفاده میشود.
برای مواردی که نحو دکوراتور مناسب نیست، میتوان از متد on_event استفاده کرد:
def my_function_handler(data):
pass
socketio.on_event('my event', my_function_handler, namespace='/test')
کلاینتها ممکن است یک کالبک تأیید دریافت (acknowledgement callback) درخواست کنند که رسیدن پیامی را که ارسال کردهاند تأیید کند. هر مقداری که از تابع گرداننده برگردانده شود، به عنوان آرگومانهای تابع کالبک به کلاینت منتقل خواهد شد:
@socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json))
return 'one', 2
در مثال بالا، تابع کالبک کلاینت با دو آرگومانِ 'one' و 2 فراخوانی خواهد شد. اگر تابع گرداننده مقداری را برنگرداند، تابع کالبک کلاینت بدون آرگومان فراخوانی میشود..SS "ارسال پیامها (Sending Messages)"
گردانندههای رویداد SocketIO که مطابق بخش قبل تعریف شدهاند، میتوانند با استفاده از توابع send() و emit() پیامهای پاسخ را به کلاینت متصل ارسال کنند.
مثالهای زیر رویدادهای دریافتی را به کلاینتِ ارسالکننده بازمیگردانند:
from flask_socketio import send, emit
@socketio.on('message')
def handle_message(message):
send(message)
@socketio.on('json')
def handle_json(json):
send(json, json=True)
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json)
توجه داشته باشید که چگونه send() و emit() بهترتیب برای رویدادهای بدوننام و نامدار استفاده میشوند.
هنگام کار با فضاهای نام (namespaces)، send() و emit() بهطور پیشفرض از فضای نام پیام ورودی استفاده میکنند. میتوان فضای نام متفاوتی را با آرگومان اختیاری namespace مشخص کرد:
@socketio.on('message')
def handle_message(message):
send(message, namespace='/chat')
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json, namespace='/chat')
برای ارسال یک رویداد با چندین آرگومان، یک تاپل (tuple) ارسال کنید:
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', ('foo', 'bar', json), namespace='/chat')
SocketIO از کالبکهای تأیید (acknowledgment callbacks) پشتیبانی میکند که دریافت شدن پیام توسط کلاینت را تأیید میکنند:
def ack():
print('message was received!')
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', json, callback=ack)
هنگام استفاده از کالبکها، کلاینت Javascript یک تابع کالبک دریافت میکند تا پس از دریافت پیام، آن را فراخوانی کند. پس از اینکه برنامهٔ کلاینت تابع کالبک را فراخوانی کرد، سرور کالبکِ سمت سرور (server-side) متناظر را فراخوانی میکند. چنانچه کالبک سمت کلاینت با آرگومانهایی فراخوانی شود، این آرگومانها به کالبک سمت سرور نیز ارائه میشوند..SS "پخش همگانی (Broadcasting)"
یکی دیگر از قابلیتهای بسیار کاربردی SocketIO، پخش همگانی پیامها است. Flask-SocketIO از این قابلیت با آرگومان اختیاری broadcast=True در توابع send() و emit() پشتیبانی میکند:
@socketio.on('my event')
def handle_my_custom_event(data):
emit('my response', data, broadcast=True)
هنگامی که پیامی با فعال بودن گزینه پخش همگانی ارسال میشود، تمام کلاینتهای متصل به آن namespace، از جمله فرستنده، آن را دریافت میکنند. زمانی که از namespaceها استفاده نمیشود، کلاینتهای متصل به namespace عمومی (global) پیام را دریافت خواهند کرد. توجه داشته باشید که برای پیامهای پخش همگانی، فراخوانها (callbacks) اجرا نمیشوند.
در تمامی مثالهای نمایشدادهشده تا این نقطه، سرور به رویدادی که توسط کلاینت ارسال شده پاسخ میدهد. اما در برخی برنامههای کاربردی، لازم است که سرور خود آغازگر یک پیام باشد. این موضوع برای ارسال اعلانها به کلاینتها جهت رویدادهایی که در سرور رخ دادهاند (بهعنوان مثال در یک ریسهٔ پسزمینه)، سودمند است. متدهای socketio.send() و socketio.emit() میتوانند برای پخش همگانی به تمام کلاینتهای متصل استفاده شوند:
def some_function():
socketio.emit('some event', {'data': 42})
توجه داشته باشید که socketio.send() و socketio.emit() توابعی یکسان با توابع آگاه از زمینه (context-aware) send() و emit() نیستند. همچنین توجه داشته باشید که در کاربرد بالا، هیچ زمینهای از کلاینت وجود ندارد؛ بنابراین broadcast=True فرض میشود و نیازی به تعیین صریح آن نیست.
اتاقها (Rooms)
در بسیاری از برنامههای کاربردی، گروهبندی کاربران در زیرمجموعههایی که بتوان آنها را با هم مورد خطاب قرار داد ضروری است. بهترین مثال، یک برنامه چت با چند اتاق است؛ جایی که کاربران پیامها را تنها از اتاق یا اتاقهایی که در آن حضور دارند دریافت میکنند، نه از دیگر اتاقهایی که کاربران دیگر در آنها هستند. Flask-SocketIO از این مفهوم اتاقها از طریق توابع join_room() و leave_room() پشتیبانی میکند:
from flask_socketio import join_room, leave_room
@socketio.on('join')
def on_join(data):
username = data['username']
room = data['room']
join_room(room)
send(username + ' has entered the room.', to=room)
@socketio.on('leave')
def on_leave(data):
username = data['username']
room = data['room']
leave_room(room)
send(username + ' has left the room.', to=room)
توابع send() و emit() یک آرگومان اختیاری to را میپذیرند که باعث میشود پیام برای تمام کلاینتهای حاضر در اتاق مشخصشده ارسال شود.
هنگام اتصال، به همهٔ کلاینتها یک اتاق اختصاص داده میشود که نام آن برابر با شناسه نشست (session ID) اتصال است و میتوان آن را از request.sid بهدست آورد. یک کلاینت مشخص میتواند به هر اتاقی با هر نامی ملحق شود. هنگامی که یک کلاینت قطع اتصال میکند، از تمام اتاقهایی که در آنها بوده حذف میشود. توابع مستقل از زمینهٔ socketio.send() و socketio.emit() نیز یک آرگومان to را برای ارسال همگانی به همهٔ کلاینتهای یک اتاق میپذیرند.
از آنجا که به همهٔ کلاینتها یک اتاق شخصی اختصاص داده میشود، برای ارسال یک پیام به یک کلاینت واحد میتوان از شناسه نشست (session ID) کلاینت بهعنوان آرگومان to استفاده کرد..SS رویدادهای اتصال (Connection Events)
Flask-SocketIO همچنین رویدادهای اتصال و قطع اتصال را ارسال میکند. مثال زیر نحوهٔ ثبت گردانندهها (handlers) را برای آنها نشان میدهد:
@socketio.on('connect')
def test_connect(auth):
emit('my response', {'data': 'Connected'})
@socketio.on('disconnect')
def test_disconnect(reason):
print('Client disconnected, reason:', reason)
آرگومان auth در گردانندهٔ اتصال اختیاری است. کلاینت میتواند از آن برای ارسال دادههای احراز هویت مانند توکنها در قالب دیکشنری استفاده کند. اگر کلاینت جزئیات احراز هویت را ارائه ندهد، این آرگومان روی None تنظیم میشود. اگر سرور یک گردانندهٔ رویداد اتصال را بدون این آرگومان تعریف کند، هرگونه دادهٔ احراز هویت ارسالشده از سوی کلاینت نادیده گرفته میشود.
گردانندهٔ رویداد اتصال میتواند برای رد اتصال مقدار False را بازگرداند، یا استثنای ConnectionRefusedError را ایجاد کند. این قابلیت بدین منظور است که بتوان کلاینت را در این مرحله احراز هویت کرد. هنگام استفاده از این استثنا، هر آرگومانی که به آن داده شود در بستهٔ خطا به کلاینت بازگردانده میشود. مثالها:
from flask_socketio import ConnectionRefusedError
@socketio.on('connect')
def connect():
if not self.authenticate(request.args):
raise ConnectionRefusedError('unauthorized!')
گردانندهٔ رویداد قطع اتصال یک آرگومان reason دریافت میکند که دلیل قطع اتصال را نشان میدهد. عضو flask_socketio.SocketIO.reason <#flask_socketio.SocketIO.reason> شامل مقادیر ثابت برای تمام دلایل احتمالی است.
توجه داشته باشید که رویدادهای اتصال و قطع اتصال بهطور جداگانه روی هر فضای نام (namespace) مورداستفاده ارسال میشوند.
فضاهای نام مبتنی بر کلاس (Class-Based Namespaces)
به عنوان جایگزینی برای گردانندههای رویداد مبتنی بر دکوراتور که در بالا توضیح داده شد، گردانندههای رویداد متعلق به یک فضای نام را میتوان به عنوان متدهای یک کلاس ایجاد کرد. کلاس flask_socketio.Namespace <#flask_socketio.Namespace> به عنوان یک کلاس پایه برای ایجاد فضاهای نام مبتنی بر کلاس ارائه شده است:
from flask_socketio import Namespace, emit
class MyCustomNamespace(Namespace):
def on_connect(self):
pass
def on_disconnect(self, reason):
pass
def on_my_event(self, data):
emit('my_response', data)
socketio.on_namespace(MyCustomNamespace('/test'))
هنگامی که از فضاهای نام مبتنی بر کلاس استفاده میشود، هر رویداد دریافتشده توسط سرور به متدی با همان نام رویداد به همراه پیشوند on_ هدایت میشود. برای مثال، رویداد my_event توسط متدی با نام on_my_event مدیریت خواهد شد. اگر رویدادی دریافت شود که متد متناظری برای آن در کلاس فضای نام تعریف نشده باشد، رویداد نادیده گرفته میشود. تمامی نامهای رویداد مورداستفاده در فضاهای نام مبتنی بر کلاس باید تنها شامل نویسههای مجاز در نام متدها باشند.
جهت سهولت کار با متدهای تعریفشده در یک فضای نام مبتنی بر کلاس، نمونهٔ فضای نام شامل نسخههایی از چندین متد کلاس flask_socketio.SocketIO <#flask_socketio.SocketIO> است که در صورت عدم ارائهٔ آرگومان namespace، بهطور پیشفرض از فضای نام مربوطه استفاده میکنند.
اگر یک رویداد هم در فضای نام مبتنی بر کلاس دارای گرداننده باشد و هم یک تابع گردانندهٔ مبتنی بر دکوراتور برای آن تعریف شده باشد، تنها تابع گردانندهٔ دکوریتشده فراخوانی میشود..SS "مدیریت خطا (Error Handling)"
Flask-SocketIO همچنین میتواند استثناها (exceptions) را مدیریت کند:
@socketio.on_error() # Handles the default namespace
def error_handler(e):
pass
@socketio.on_error('/chat') # handles the '/chat' namespace
def error_handler_chat(e):
pass
@socketio.on_error_default # handles all namespaces without an explicit error handler
def default_error_handler(e):
pass
توابع گرداننده خطا شیء استثنا را به عنوان یک آرگومان دریافت میکنند.
آرگومانهای پیام و داده مربوط به درخواست فعلی را نیز میتوان با متغیر request.event بررسی کرد، که برای ثبت لاگ خطا و اشکالزدایی بیرون از گرداننده رویداد مفید است:
from flask import request
@socketio.on("my error event")
def on_my_event(data):
raise RuntimeError()
@socketio.on_error_default
def default_error_handler(e):
print(request.event["message"]) # "my error event"
print(request.event["args"]) # (data,)
اشکالزدایی و عیبیابی (Debugging and Troubleshooting)
برای کمک به اشکالزدایی مشکلات، سرور میتواند طوری پیکربندی شود که لاگها را به ترمینال خروجی دهد:
socketio = SocketIO(logger=True, engineio_logger=True)
آرگومان logger لاگگیری مربوط به پروتکل Socket.IO را کنترل میکند، در حالی که engineio_logger لاگهایی را کنترل میکند که از لایه انتقال سطحپایین Engine.IO منشأ میگیرند. این آرگومانها را میتوان برای ارسال لاگها به stderr روی True تنظیم کرد، یا روی شیئی سازگار با بستهی logging در Python که لاگها باید به آن فرستاده شوند. مقدار False لاگگیری را غیرفعال میکند.
لاگگیری میتواند به شناسایی علت مشکلات اتصال، پاسخهای 400، عملکرد ضعیف و سایر مسائل کمک کند.
نکات پیادهسازی (IMPLEMENTATION NOTES)
دسترسی به سراسریهای زمینه Flask (Access to Flask's Context Globals)
گردانندههای رویدادهای SocketIO با گردانندههای مسیرها (routes) متفاوت هستند و این موضوع سردرگمیهای زیادی درباره کارهایی که میتوان یا نمیتوان در یک گرداننده SocketIO انجام داد ایجاد میکند. تفاوت اصلی در این است که تمام رویدادهای SocketIO ایجاد شده برای یک کلاینت، در زمینه (context) یک درخواست منفرد و طولانیمدت رخ میدهند.
با وجود این تفاوتها، Flask-SocketIO تلاش میکند با شبیهسازی محیط به یک درخواست معمولی HTTP، کار با گردانندههای رویداد SocketIO را سادهتر سازد. فهرست زیر مواردی که کار میکنند و مواردی که کار نمیکنند را شرح میدهد:
- پیش از فراخوانی یک گرداننده رویداد، یک زمینه برنامه (application context) وارد (push) میشود که current_app و g را در دسترس گرداننده قرار میدهد.
- پیش از فراخوانی گرداننده، یک زمینه درخواست (request context) نیز وارد میشود که request و session را نیز در دسترس قرار میدهد. اما توجه داشته باشید که رویدادهای WebSocket درخواستهای مجزای مرتبط با خود را ندارند، بنابراین زمینه درخواستی که اتصال را آغاز کرده است، برای تمام رویدادهایی که در طول عمر اتصال ارسال میشوند وارد میشود.
- متغیر سراسری زمینه request با عضو sid گسترش یافته است که روی یک شناسه نشست (session ID) یکتا برای اتصال تنظیم میشود. این مقدار به عنوان یک اتاق (room) اولیه که کلاینت به آن اضافه میشود، مورد استفاده قرار میگیرد.
- متغیر سراسری زمینه request با اعضای namespace و event گسترش یافته است که شامل فضای نام و آرگومانهای رویداد در حال پردازش هستند. عضو event یک دیکشنری با کلیدهای message و args است.
- متغیر سراسری زمینه session به شیوهای متفاوت از درخواستهای معمولی رفتار میکند. نسخهای از نشست کاربر در زمان برقراری اتصال SocketIO در دسترس گردانندههایی که در زمینه آن اتصال فراخوانی میشوند قرار میگیرد. اگر یک گرداننده SocketIO نشست را تغییر دهد، نشست تغییریافته برای گردانندههای بعدی SocketIO حفظ خواهد شد، اما گردانندههای مسیر معمولی HTTP این تغییرات را نخواهند دید. در عمل، هنگامی که یک گرداننده SocketIO نشست را تغییر میدهد، یک انشعاب ("fork") از نشست به طور اختصاصی برای این گردانندهها ایجاد میشود. دلیل فنی این محدودیت آن است که برای ذخیره نشست کاربر، نیاز است یک کوکی به کلاینت فرستاده شود و این امر نیازمند درخواست و پاسخ HTTP است که در اتصال SocketIO وجود ندارند. هنگام استفاده از نشستهای سمت سرور مانند موارد ارائهشده توسط افزونههای Flask-Session یا Flask-KVSession، تغییرات اعمالشده بر نشست در گردانندههای مسیر HTTP توسط گردانندههای SocketIO قابل مشاهده خواهد بود، مادامی که نشست در گردانندههای SocketIO دستکاری نشود.
- قلابهای before_request و after_request برای گردانندههای رویداد SocketIO فراخوانی نمیشوند.
- گردانندههای
SocketIO
میتوانند
دکوراتورهای
سفارشی
بپذیرند،
اما با توجه
به اینکه در
طول اتصال SocketIO
مفهومی به
نام شیء Response
وجود
ندارد،
بیشتر
دکوراتورهای
Flask برای
استفاده در
یک
گرداننده SocketIO
مناسب
نخواهند
بود.
یک نیاز معمول در برنامهها، اعتبارسنجی هویت کاربران است. سازوکارهای سنتی مبتنی بر فرمهای وب و درخواستهای HTTP در یک اتصال SocketIO قابل استفاده نیستند، چرا که جایی برای ارسال درخواستها و پاسخهای HTTP وجود ندارد. در صورت نیاز، یک برنامه میتواند یک فرم ورود سفارشی را پیادهسازی کند که هنگام فشرده شدن دکمهٔ ارسال توسط کاربر، اعتبارنامهها را در قالب یک پیام SocketIO به سرور بفرستد.
با این حال، در بیشتر موارد راحتتر است که فرآیند سنتی احراز هویت پیش از برقراری اتصال SocketIO انجام شود. سپس هویت کاربر میتواند در نشست کاربر (user session) یا در یک کوکی ثبت گردد و بعداً هنگام برقراری اتصال SocketIO، آن اطلاعات برای گردانندههای رویداد SocketIO قابل دسترسی خواهد بود.
بازبینیهای اخیر پروتکل Socket.IO قابلیتی برای ارسال یک دیکشنری حاوی اطلاعات احراز هویت در حین برقراری اتصال را در بر دارند. این یک مکان ایدهآل برای کلاینت است تا یک توکن یا سایر جزئیات احراز هویت را درج کند. اگر کلاینت از این قابلیت استفاده کند، سرور این دیکشنری را همانطور که در بالا نشان داده شد، به عنوان یک آرگومان به گردانندهٔ رویداد connect ارائه خواهد داد.
استفاده از Flask-Login با Flask-SocketIO
Flask-SocketIO میتواند به اطلاعات ورودی که توسط Flask-Login https://flask-login.readthedocs.org/en/latest نگهداری میشود دسترسی داشته باشد. پس از انجام یک احراز هویت معمول در Flask-Login و فراخوانی تابع login_user() جهت ثبت کاربر در نشست کاربر، هر اتصال SocketIO به متغیر زمینهای current_user دسترسی خواهد داشت:
@socketio.on('connect')
def connect_handler():
if current_user.is_authenticated:
emit('my response',
{'message': '{0} has joined'.format(current_user.name)},
broadcast=True)
else:
return False # not allowed here
توجه داشته باشید که دکوراتور login_required نمیتواند برای گردانندههای رویداد SocketIO استفاده شود، اما یک دکوراتور سفارشی که کاربران احراز هویتنشده را قطع میکند میتواند به صورت زیر ایجاد شود:
import functools
from flask import request
from flask_login import current_user
from flask_socketio import disconnect, emit
def authenticated_only(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
if not current_user.is_authenticated:
disconnect()
else:
return f(*args, **kwargs)
return wrapped
@socketio.on('my event')
@authenticated_only
def handle_my_custom_event(data):
emit('my response', {'message': '{0} has joined'.format(current_user.name)},
broadcast=True)
استقرار (DEPLOYMENT)
گزینههای متعددی برای استقرار یک سرور Flask-SocketIO وجود دارد، از موارد ساده گرفته تا ساختارهای فوقالعاده پیچیده. در این بخش، پرکاربردترین گزینهها شرح داده شدهاند.
سرور توکار (Embedded Server)
سادهترین راهبرد استقرار، راهاندازی وبسرور با فراخوانی socketio.run(app) است، همانطور که در مثالهای بالا نشان داده شد. این دستور بستههای نصبشده را برای یافتن بهترین وبسرور موجود بررسی کرده و برنامه را روی آن اجرا میکند. گزینههای وبسرور فعلی که مورد ارزیابی قرار میگیرند عبارتاند از eventlet، gevent و سرور توسعهٔ Flask.
اگر eventlet یا gevent در دسترس باشند، socketio.run(app) یک سرور آمادهٔ محیط عملیاتی را با استفاده از یکی از این چارچوبها راهاندازی میکند. اگر هیچیک از اینها نصب نشده باشند، وبسرور توسعهٔ Flask به کار گرفته میشود، و در این حالت، سرور برای استفاده در محیط عملیاتی در نظر گرفته نشده است.
متأسفانه این گزینه هنگام استفاده از gevent با uWSGI در دسترس نیست. برای اطلاعات بیشتر دربارهٔ این گزینه، بخش uWSGI را در زیر ببینید..SS "وبسرور Gunicorn (Gunicorn Web Server)"
یک جایگزین برای socketio.run(app) استفاده از gunicorn http://gunicorn.org بهعنوان وبسرور، با استفاده از ورکرهای eventlet یا gevent است. برای این گزینه، علاوهبر gunicorn، باید eventlet یا gevent نیز نصب شده باشد. خط فرمانی که سرور eventlet را از طریق gunicorn راهاندازی میکند عبارت است از:
gunicorn --worker-class eventlet -w 1 module:app
اگر ترجیح میدهید از gevent استفاده کنید، دستور راهاندازی سرور به این صورت است:
gunicorn -k gevent -w 1 module:app
هنگام استفاده از gunicorn به همراه ورکر gevent و پشتیبانی WebSocket ارائهشده توسط gevent-websocket، دستور راهاندازی سرور باید تغییر کند تا یک وبسرور سفارشی gevent که از پروتکل WebSocket پشتیبانی میکند انتخاب شود. دستور تغییریافته عبارت است از:
gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 module:app
گزینه سوم در Gunicorn، استفاده از ورکر ریسهای (threaded worker) به همراه بسته simple-websocket https://github.com/miguelgrinberg/simple-websocket جهت پشتیبانی از WebSocket است. این راهحل بهویژه برای برنامههایی که بار پردازشی بالایی روی CPU دارند یا به دلایل دیگر با استفاده eventlet و gevent از گرینتردها (green threads) ناسازگار هستند، بسیار مناسب است. دستور راهاندازی یک وبسرور ریسهای به شرح زیر است:
gunicorn -w 1 --threads 100 module:app
در تمامی این دستورها، module همان ماژول یا بسته پایتون است که نمونه برنامه (application instance) را تعریف میکند، و app خود نمونه برنامه است.
به دلیل محدودیت در الگوریتم توزیع بار (load balancing) استفادهشده توسط gunicorn، استفاده از بیش از یک فرایند ورکر هنگام بهکارگیری این وبسرور امکانپذیر نیست. به همین دلیل، تمامی مثالهای بالا شامل گزینه -w 1 هستند.
راهکار جایگزین جهت استفاده از چندین فرایند ورکر با gunicorn، راهاندازی چندین نمونه تکورکری (single-worker) و قرار دادن آنها در پشت یک توزیعکننده بار قدرتمندتر مانند nginx https://www.nginx.com است.
وبسرور uWSGI (uWSGI Web Server)
هنگام استفاده از سرور uWSGI در ترکیب با gevent، سرور Socket.IO میتواند از پشتیبانی بومی uWSGI از WebSocket بهرهمند شود.
توضیح کامل پیکربندی و نحوه استفاده از سرور uWSGI خارج از محدوده این مستندات است. سرور uWSGI بسته نسبتاً پیچیدهای است که مجموعه بزرگ و جامعی از گزینهها را ارائه میدهد. این سرور برای در دسترس بودن انتقال WebSocket (WebSocket transport) باید با پشتیبانی از WebSocket و SSL کامپایل شده باشد. به عنوان مقدمه، دستور زیر یک سرور uWSGI را برای برنامه نمونه app.py روی درگاه 5000 راهاندازی میکند:
$ uwsgi --http :5000 --gevent 1000 --http-websockets --master --wsgi-file app.py --callable app
میتوان از nginx بهعنوان یک پروکسی معکوس (reverse proxy) فرانتاند برای هدایت درخواستها به برنامه کاربردی استفاده کرد. با این حال، تنها نگارشهای 1.4 و جدیدتر nginx از پروکسی کردن پروتکل WebSocket پشتیبانی میکنند. در ادامه یک پیکربندی پایهای nginx آورده شده است که درخواستهای HTTP و WebSocket را پروکسی میکند:
server {
listen 80;
server_name _;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
location /static/ {
alias <path-to-your-application>/static/;
expires 30d;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:5000/socket.io;
}
}
مثال بعدی پشتیبانی از توازن بار (load balancing) میان چندین سرور Socket.IO را اضافه میکند:
upstream socketio_nodes {
ip_hash;
server 127.0.0.1:5000;
server 127.0.0.1:5001;
server 127.0.0.1:5002;
# to scale the app, just add more nodes here!
}
server {
listen 80;
server_name _;
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
location /static/ {
alias <path-to-your-application>/static/;
expires 30d;
}
location /socket.io {
include proxy_params;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://socketio_nodes/socket.io;
}
}
گرچه مثالهای بالا میتوانند بهعنوان یک پیکربندی اولیه به کار روند، توجه داشته باشید که راهاندازی nginx در محیط عملیاتی (production) به پیکربندی کاملتری نیاز خواهد داشت که سایر جنبههای استقرار نظیر پشتیبانی از SSL را پوشش دهد..SS استفاده از چندین Worker
Flask-SocketIO از نگارش 2.0 به بعد، از چندین worker پشت یک متعادلکننده بار (load balancer) پشتیبانی میکند. استقرار چندین worker به برنامههایی که از Flask-SocketIO استفاده میکنند این امکان را میدهد تا اتصالات کلاینتها را میان چندین پردازه و میزبان توزیع کرده و از این طریق برای پشتیبانی از تعداد بسیار زیادی کلاینت همروند مقیاسپذیر شوند.
برای استفاده از چندین worker در Flask-SocketIO دو پیشنیاز وجود دارد:
- متعادلکننده بار باید بهگونهای پیکربندی شود که تمامی درخواستهای HTTP ارسالی از سوی یک کلاینت مشخص را همواره به همان worker یکسان هدایت کند. این ویژگی گاهی اوقات با نام "نشستهای چسبنده (sticky sessions)" شناخته میشود. در nginx، از دستورالعمل ip_hash برای دستیابی به این هدف استفاده کنید. از Gunicorn نمیتوان با چندین worker استفاده کرد زیرا الگوریتم متعادلسازی بار آن از sticky sessions پشتیبانی نمیکند.
- از آنجا که هر یک از سرورها تنها مالک زیرمجموعهای از اتصالات کلاینتها هستند، از یک صف پیام (message queue) مانند Redis یا RabbitMQ توسط سرورها برای هماهنگسازی عملیات پیچیدهای نظیر انتشار همگانی (broadcasting) و اتاقها (rooms) استفاده میشود.
هنگام کار با یک صف پیام، وابستگیهای بیشتری وجود دارند که باید نصب شوند:
- برای Redis، بسته redis باید نصب شود (pip install redis).
- برای RabbitMQ، بسته kombu باید نصب شود (pip install kombu).
- برای Kafka، بسته kafka-python باید نصب شود (pip install kafka-python).
- برای سایر صفهای پیام پشتیبانیشده توسط Kombu، به مستندات Kombu در http://docs.celeryproject.org/projects/kombu/en/latest/introduction.html#transport-comparison مراجعه کنید تا دریابید چه وابستگیهایی مورد نیاز است.
- اگر از eventlet یا gevent استفاده میشود، معمولاً وصلهکاری پویا (monkey patching) کتابخانه استاندارد پایتون برای واداشتن بسته صف پیام به استفاده از توابع و کلاسهای سازگار با کوروتین (coroutine) مورد نیاز است.
برای eventlet، عمل monkey patching با دستورات زیر انجام میشود:
import eventlet eventlet.monkey_patch()
برای gevent، میتوانید کتابخانه استاندارد را با دستورات زیر monkey patch کنید:
from gevent import monkey monkey.patch_all()
در هر دو مورد توصیه میشود که monkey patching را در ابتدای اسکریپت اصلی خود، حتی بالاتر از دستورات import اعمال کنید.
برای راهاندازی چندین سرور Flask-SocketIO، ابتدا باید اطمینان حاصل کنید که سرویس صف پیام در حال اجرا است. برای راهاندازی یک سرور Socket.IO و اتصال آن به صف پیام، آرگومان message_queue را به سازنده SocketIO اضافه کنید:
socketio = SocketIO(app, message_queue='redis://')
مقدار آرگومان message_queue نشانی URL اتصال سرویس صف مورد استفاده است. برای یک صف redis که روی همان میزبان سرور اجرا میشود، میتوان از نشانی URL با قالب 'redis://' استفاده کرد. بههمین ترتیب، برای یک صف پیشفرض RabbitMQ نشانی URL با قالب 'amqp://' قابل استفاده است. برای Kafka از یک نشانی URL با قالب kafka:// استفاده کنید. بسته Kombu بخشی در مستندات http://docs.celeryproject.org/projects/kombu/en/latest/userguide/connections.html?highlight=urls#urls دارد که ساختار URLها را برای تمام صفهای پشتیبانیشده شرح میدهد..SS ارسال از یک فرایند خارجی (Emitting from an External Process)
در بسیاری از انواع برنامهها، ارسال رویدادها از فرایندی که سرور SocketIO نیست، برای نمونه یک worker در Celery، ضروری است. اگر سرور یا سرورهای SocketIO همانطور که در بخش پیشین نشان داده شد برای شنود روی یک صف پیام پیکربندی شده باشند، هر فرایند دیگری میتواند نمونهٔ SocketIO خود را ایجاد کرده و از آن برای ارسال رویدادها به همان شیوهای که سرور انجام میدهد، استفاده کند.
برای نمونه، برای برنامهای که روی یک وبسرور eventlet اجرا میشود و از یک صف پیام Redis استفاده میکند، اسکریپت Python زیر یک رویداد را به همهٔ کلاینتها همهپخشی (broadcast) میکند:
socketio = SocketIO(message_queue='redis://')
socketio.emit('my event', {'data': 'foo'}, namespace='/test')
هنگام استفاده از نمونهٔ SocketIO به این روش، نمونهٔ برنامهٔ Flask به سازنده (constructor) ارسال نمیشود.
آرگومان channel در SocketIO میتواند برای انتخاب یک کانال ارتباطی مشخص از طریق صف پیام استفاده شود. استفاده از یک نام کانال سفارشی زمانی لازم است که چندین سرویس مستقل SocketIO از یک صف مشترک استفاده میکنند.
هنگامی که eventlet یا gevent استفاده میشوند، Flask-SocketIO اقدام به اعمال monkey patching نمیکند. اما هنگام کار با یک صف پیام، بسیار محتمل است که بستهٔ Python برقرارکنندهٔ ارتباط با سرویس صف پیام، در صورت عدم اعمال monkey patching بر روی کتابخانهٔ استاندارد Python، معلق (hang) شود.
توجه به این نکته مهم است فرایندی خارجی که قصد اتصال به سرور SocketIO را دارد، نیازی به استفاده از eventlet یا gevent مانند سرور اصلی ندارد. اینکه سرور از یک فریمورک coroutine استفاده کند در حالی که فرایند خارجی چنین نمیکند، مشکلی ایجاد نمیکند. برای نمونه، نیازی نیست workerهای Celery تنها به این دلیل که سرور اصلی چنین میکند، برای استفاده از eventlet یا gevent پیکربندی شوند. اما اگر فرایند خارجی شما بنا به هر دلیلی از یک فریمورک coroutine استفاده میکند، در این صورت احتمالاً monkey patching مورد نیاز خواهد بود تا صف پیام به توابع و کلاسهای سازگار با coroutine دسترسی داشته باشد.
کنترلهای مبدأ متقابل (Cross-Origin Controls)
به دلایل امنیتی، این سرور به طور پیشفرض یک سیاست مبدأ یکسان (same-origin policy) را اعمال میکند. در عمل، این به معنای موارد زیر است:
- اگر یک درخواست ورودی HTTP یا WebSocket شامل هدر Origin باشد، این هدر باید با طرحواره (scheme) و میزبان (host) نشانی URL اتصال مطابقت داشته باشد. در صورت عدم تطابق، پاسخی با کد وضعیت 400 بازگردانده شده و اتصال رد میشود.
- هیچ محدودیتی بر روی درخواستهای ورودی فاقد هدر Origin اعمال نمیشود.
در صورت نیاز، گزینهٔ cors_allowed_origins میتواند برای مجاز کردن سایر مبدأها استفاده شود. این آرگومان میتواند روی یک رشته برای تعیین یک مبدأ مجاز واحد، یا یک لیست برای مجاز کردن چندین مبدأ تنظیم شود. مقدار ویژهٔ '*' میتواند برای دستور دادن به سرور جهت مجاز کردن همهٔ مبدأها به کار رود، اما این کار باید با احتیاط انجام شود، چرا که ممکن است سرور را در برابر حملات جعل درخواست میانوبگاهی (CSRF) آسیبپذیر سازد.
ارتقا به FLASK-SOCKETIO 5.X از نسخههای 4.X (UPGRADING TO FLASK-SOCKETIO 5.X FROM THE 4.X RELEASES)
پروتکل Socket.IO اخیراً مجموعهای از تغییرات ناسازگار با گذشته (backwards incompatible) را ارائه کرده است. انتشارهای نسخهٔ 5.x از Flask-SocketIO این تغییرات را به کار گرفتهاند و به همین دلیل تنها با کلاینتهایی قابل استفاده هستند که به نسخهٔ فعلی پروتکل بهروزرسانی شده باشند. به ویژه، این بدان معناست که کلاینت JavaScript باید به نسخهٔ 3.x ارتقا داده شود، و اگر کلاینت شما به آخرین نسخه از پروتکل Socket.IO ارتقا نیافته است، باید از انتشارهای Flask-SocketIO 4.x استفاده کنید.
تغییرات پروتکل زیر حائز اهمیت هستند، زیرا ممکن است بر برنامههای موجود تأثیر بگذارند:
- فضای نام پیشفرض '/' دیگر به طور خودکار متصل نمیشود و اکنون همانند سایر فضاهای نام با آن رفتار میشود.
- هر اتصال فضای نام، مقدار sid مخصوص به خود را دارد که با دیگران متفاوت بوده و با sid مربوط به Engine.IO نیز متفاوت است.
- اکنون Flask-SocketIO از مقادیر بازه و مهلت زمانی (timeout) مشابه در پیادهسازی مرجع JavaScript استفاده میکند که به ترتیب 25 و 5 ثانیه هستند.
- سازوکار ping/pong معکوس شده است. در نسخهٔ فعلی پروتکل، سرور یک ping ارسال میکند و کلاینت با یک pong پاسخ میدهد.
- حداکثر اندازهٔ مجاز پیشفرض برای بار داده (payload) در بستههای long--polling از 100MB به 1MB کاهش یافته است.
- کوکی io دیگر به صورت پیشفرض برای کلاینت ارسال نمیشود.
- class flask_socketio.SocketIO(app=None, **kwargs)
- ایجاد یک سرور Flask-SocketIO.
- پارامترها
- app -- نمونه برنامه flask. اگر نمونه برنامه در زمان نمونهسازی این کلاس در دسترس نباشد، پس از در دسترس قرار گرفتن آن، socketio.init_app(app) را فراخوانی کنید.
- manage_session -- اگر روی True تنظیم شود، این افزونه نشست کاربر را برای رویدادهای Socket.IO مدیریت میکند. اگر روی False تنظیم شود، از مدیریت نشست خود Flask استفاده میشود. هنگام استفاده از نشستهای مبتنی بر کوکی Flask، توصیه میشود این گزینه را روی مقدار پیشفرض True رها کنید. هنگام استفاده از نشستهای سمت سرور، مقدار False امکان اشتراکگذاری نشست کاربر را میان مسیرهای HTTP و رویدادهای Socket.IO فراهم میسازد.
- message_queue -- یک URL اتصال برای سرویس صف پیام که سرور میتواند برای ارتباط چندفرایندی از آن استفاده کند. هنگام استفاده از یک فرایند سرور منفرد، نیازی به صف پیام نیست.
- channel -- نام کانال، هنگام استفاده از صف پیام. اگر کانالی مشخص نشود، از یک کانال پیشفرض استفاده خواهد شد. اگر چندین کلاستر از فرایندهای SocketIO نیاز به استفاده از یک صف پیام مشترک بدون تداخل با یکدیگر داشته باشند، هر کلاستر باید از کانال متفاوتی استفاده کند.
- path -- مسیری که سرور Socket.IO در آن ارائه میشود. پیشفرض 'socket.io' است. این مقدار را تغییر ندهید مگر آنکه دقیقا بدانید چه میکنید.
- resource -- نام مستعار برای path.
- kwargs -- گزینههای سرور Socket.IO و Engine.IO.
گزینههای سرور Socket.IO در زیر به تفصیل شرح داده شدهاند:
- پارامترها
- client_manager -- نمونه مدیر کلاینت که فهرست کلاینتها را مدیریت خواهد کرد. در صورت حذف این گزینه، فهرست کلاینتها در یک ساختار درونحافظهای ذخیره میشود، بنابراین استفاده از چندین سرور متصل امکانپذیر نخواهد بود.
- logger -- برای فعالسازی ثبت گزارش آن را روی True تنظیم کنید یا یک شیء ثبتکننده گزارش بفرستید. برای غیرفعالسازی ثبت گزارش آن را روی False تنظیم کنید. پیشفرض False است. توجه داشته باشید که خطاهای مهلک حتی زمانی که logger روی False باشد نیز ثبت میشوند.
- serializer -- روش سریالسازی مورد استفاده هنگام ارسال بستهها. مقادیر معتبر عبارتند از 'default'، 'pickle'، 'msgpack' و 'cbor'. به عنوان جایگزین، میتوان یک زیرکلاس از کلاس Packet به همراه پیادهسازیهای سفارشی از توابع encode() و decode() ارائه داد. کلاینت و سرور باید از سریالکنندههای سازگار استفاده کنند.
- json -- یک ماژول JSON جایگزین برای کدگذاری و رمزگشایی بستهها. ماژولهای سفارشی json باید توابع dumps و loads سازگار با نسخههای کتابخانه استاندارد را داشته باشند. این یک تنظیم در سطح کل فرایند است و تمام سرورها و کلاینتهای ساختهشده باید از ماژول JSON یکسانی استفاده کنند.
- async_handlers -- اگر روی True تنظیم شود، کنترلکنندههای رویداد برای یک کلاینت در ریسمانهای جداگانه اجرا میشوند. برای اجرای همگام کنترلکنندهها برای یک کلاینت، آن را روی False تنظیم کنید. پیشفرض True است.
- always_connect -- هنگامی که روی False تنظیم شود، اتصالات جدید مشروط هستند تا زمانی که کنترلکننده connect چیزی غیر از False برگرداند، که در آن زمان پذیرفته میشوند. هنگامی که روی True تنظیم شود، اتصالات بلافاصله پذیرفته میشوند و سپس اگر کنترلکننده connect مقدار False را برگرداند، دستور قطع اتصال صادر میشود. اگر نیاز دارید از درون کنترلکننده connect رویدادها را ارسال کنید و کلاینت شما با دریافت رویدادها پیش از پذیرش اتصال دچار سردرگمی میشود، این گزینه را روی True تنظیم کنید. در هر حالت دیگری از مقدار پیشفرض False استفاده کنید.
- namespaces -- فهرستی از فضاهای نام که علاوه بر هر فضای نام دارای کنترلکننده تعریفشده، پذیرفته میشوند. پیشفرض ['/'] است که همیشه اتصالات به فضای نام پیشفرض را میپذیرد. برای پذیرش تمام فضاهای نام، آن را روی '*' تنظیم کنید.
پیکربندی سرور Engine.IO از تنظیمات زیر پشتیبانی میکند:
- پارامترها
- async_mode -- مدل ناهمگام مورد استفاده. برای مشاهده توضیحات گزینههای موجود به بخش استقرار (Deployment) در مستندات مراجعه کنید. حالتهای ناهمگام معتبر عبارتند از "threading"، "eventlet"، "gevent" و "gevent_uwsgi". اگر این آرگومان مشخص نشود، ابتدا "eventlet"، سپس "gevent_uwsgi"، سپس "gevent" و در نهایت "threading" بررسی میشود. نخستین حالت ناهمگامی که تمام وابستگیهای آن نصب باشد انتخاب خواهد شد.
- ping_interval -- بازه زمانی به ثانیه که در آن سرور به کلاینت پینگ میفرستد. پیشفرض ۲۵ ثانیه است. برای کنترل پیشرفتهتر، میتوان یک تاپل دو عنصری مشخص کرد که در آن عدد اول بازه پینگ و عدد دوم مهلت اضافی اعمالشده توسط سرور است.
- ping_timeout -- مدت زمانی به ثانیه که کلاینت پیش از قطع اتصال منتظر پاسخ سرور میماند. پیشفرض ۲۰ ثانیه است.
- max_http_buffer_size -- حداکثر اندازه مجاز برای پیامهای ورودی. مقدار پیشفرض ۱,۰۰۰,۰۰۰ بایت است. علیرغم نام آن، مقدار تعیینشده در این آرگومان برای هر دو نوع اتصال HTTP long-polling و WebSocket اعمال میشود.
- allow_upgrades -- تعیین اینکه آیا ارتقای پروتکلهای انتقال مجاز است یا خیر. پیشفرض True است.
- http_compression -- تعیین اینکه آیا در زمان استفاده از روش انتقال polling، بستهها فشردهسازی شوند یا خیر. پیشفرض True است.
- compression_threshold -- پیامها تنها در صورتی فشرده میشوند که اندازه بایتی آنها بیشتر از این مقدار باشد. پیشفرض ۱۰۲۴ بایت است.
- cookie -- اگر به صورت یک رشته تنظیم شود، نام کوکی HTTP خواهد بود که سرور به کلاینت بازمیگرداند و حاوی شناسه نشست کلاینت است. اگر به صورت یک دیکشنری تنظیم شود، کلید 'name' حاوی نام کوکی خواهد بود و سایر کلیدها ویژگیهای کوکی را تعیین میکنند، که در آن مقدار هر ویژگی میتواند یک رشته، یک فراخوانیپذیر بدون آرگومان، یا یک مقدار بولی باشد. اگر روی None (پیشفرض) تنظیم شود، کوکی به کلاینت ارسال نخواهد شد.
- cors_allowed_origins -- مبدا یا فهرستی از مبداهایی که مجاز به اتصال به این سرور هستند. به طور پیشفرض تنها همان مبدا مجاز است. این آرگومان را روی '*' یا ['*'] تنظیم کنید تا تمام مبداها مجاز شوند، یا روی [] برای غیرفعالسازی مدیریت CORS.
- cors_credentials -- تعیین اینکه آیا اطلاعات اعتبارسنجی (کوکیها، احراز هویت) در درخواستهای ارسالی به این سرور مجاز هستند یا خیر. پیشفرض True است.
- monitor_clients -- اگر روی True تنظیم شود، یک وظیفه پسزمینه بسته شدن کلاینتهای غیرفعال را تضمین میکند. برای غیرفعالسازی وظیفه پایش (توصیه نمیشود)، آن را روی False تنظیم کنید. پیشفرض True است.
- transports -- فهرست روشهای انتقال مجاز. روشهای انتقال معتبر عبارتند از 'polling' و 'websocket'. پیشفرض ['polling', 'websocket'] است.
- engineio_logger -- برای فعالسازی ثبت گزارشهای Engine.IO آن را روی True تنظیم کنید یا یک شیء ثبتکننده گزارش بفرستید. برای غیرفعالسازی ثبت گزارش آن را روی False تنظیم کنید. پیشفرض False است. توجه داشته باشید که خطاهای مهلک حتی زمانی که engineio_logger روی False باشد نیز ثبت میشوند.
- class reason
- دلایل قطع اتصال.
- PING_TIMEOUT = 'ping timeout'
- پایان مهلت زمانی پینگ (Ping timeout).
- SERVER_DISCONNECT = 'server disconnect'
- قطع ارتباط آغازشده از سوی سرور.
- TRANSPORT_CLOSE = 'transport close'
- بسته شدن لایهٔ انتقال (Transport close).
- TRANSPORT_ERROR = 'transport error'
- خطای لایهٔ انتقال (Transport error).
- on(message, namespace=None)
- دکوراتوری
برای ثبت یک
گردانندهٔ
رویداد SocketIO.
این دکوراتور باید روی گردانندههای رویداد SocketIO اعمال شود. مثال:
@socketio.on('my event', namespace='/chat')
def handle_my_custom_event(json):
print('received json: ' + str(json))
- پارامترها
- message -- نام رویداد. این معمولاً یک رشتهٔ تعریفشده توسط کاربر است، اما چند نام رویداد از قبل تعریف شدهاند. از 'message' برای تعریف گردانندهای که بار دادهٔ (payload) رشتهای دریافت میکند، از 'json' برای تعریف گردانندهای که بار دادهٔ شیء JSON دریافت میکند، و از 'connect' یا 'disconnect' برای ایجاد گردانندههای رویدادهای اتصال و قطع ارتباط استفاده کنید.
- namespace -- فضای نامی که گرداننده باید در آن ثبت شود. پیشفرض، فضای نام سراسری است.
- on_error(namespace=None)
- دکوراتوری
برای تعریف
یک
گردانندهٔ
خطای
سفارشی
برای
رویدادهای
SocketIO.
این دکوراتور میتواند روی تابعی اعمال شود که به عنوان گردانندهٔ خطا برای یک فضای نام عمل میکند. این گرداننده زمانی فراخوانی میشود که یک گردانندهٔ رویداد SocketIO استثنایی (exception) ایجاد کند. تابع گرداننده باید یک آرگومان بپذیرد که همان استثنای رخداده است. مثال:
@socketio.on_error(namespace='/chat')
def chat_error_handler(e):
print('An error has occurred: ' + str(e))
- پارامترها
- namespace -- فضای نامی که گردانندهٔ خطا برای آن ثبت میشود. پیشفرض، فضای نام سراسری است.
- on_error_default(exception_handler)
- دکوراتوری
برای تعریف
یک
گردانندهٔ
خطای
پیشفرض
برای
رویدادهای
SocketIO.
این دکوراتور میتواند روی تابعی اعمال شود که به عنوان گردانندهٔ خطای پیشفرض برای هر فضای نامی که گردانندهٔ مشخصی ندارد، عمل کند. مثال:
@socketio.on_error_default
def error_handler(e):
print('An error has occurred: ' + str(e))
- on_event(message, handler, namespace=None)
- ثبت یک
گردانندهٔ
رویداد SocketIO.
on_event نسخهٔ بدون دکوراتور 'on' است.
مثال:
def on_foo_event(json):
print('received json: ' + str(json))
socketio.on_event('my event', on_foo_event, namespace='/chat')
- پارامترها
- message -- نام رویداد. این معمولاً یک رشتهٔ تعریفشده توسط کاربر است، اما چند نام رویداد از قبل تعریف شدهاند. از 'message' برای تعریف گردانندهای که بار دادهٔ رشتهای دریافت میکند، از 'json' برای تعریف گردانندهای که بار دادهٔ شیء JSON دریافت میکند، و از 'connect' یا 'disconnect' برای ایجاد گردانندههای رویدادهای اتصال و قطع ارتباط استفاده کنید.
- handler -- تابعی که رویداد را پردازش (رسیدگی) میکند.
- namespace -- فضای نامی که گرداننده باید در آن ثبت شود. پیشفرض، فضای نام سراسری است.
- event(*args, **kwargs)
- دکوراتوری
برای ثبت یک
گردانندهٔ
رویداد.
این یک نسخهٔ سادهشده از متد on() است که نام رویداد را از تابع دکورهشده میگیرد.
نمونه کاربرد:
@socketio.event
def my_event(data):
print('Received data: ', data)
مثال بالا معادل است با:
@socketio.on('my_event')
def my_event(data):
print('Received data: ', data)
یک فضای نام سفارشی میتواند به عنوان یک آرگومان به این دکوراتور داده شود:
@socketio.event(namespace='/test')
def my_event(data):
print('Received data: ', data)
این تابع یک رویداد SocketIO را به یک یا چند کلاینت متصل ارسال (emit) میکند. میتوان یک بسته داده JSON را به عنوان بار داده (payload) به رویداد پیوست کرد. این تابع میتواند خارج از بافت (context) رویداد SocketIO استفاده شود، بنابراین برای زمانهایی که سرور مبدا ایجاد یک رویداد است (خارج از بافت کلاینت)، مانند یک گرداننده درخواست معمولی HTTP یا یک وظیفه پسزمینه (background task) مناسب است. مثال:
@app.route('/ping')
def ping():
socketio.emit('ping event', {'data': 42}, namespace='/chat')
- پارامترها
- event -- نام رویداد کاربری برای ارسال.
- args -- یک دیکشنری شامل دادههای JSON جهت ارسال به عنوان بار داده (payload).
- namespace -- فضای نامی (namespace) که پیام باید تحت آن ارسال شود. پیشفرض، فضای نام عمومی (global) است.
- to -- ارسال پیام به تمام کاربران موجود در اتاق (room) مشخصشده، یا به کاربری با شناسه نشست (session ID) دادهشده. اگر این پارامتر گنجانده نشود، رویداد به تمام کاربران متصل ارسال میشود.
- include_self -- مقدار True برای گنجاندن فرستنده هنگام انتشار فراگیر (broadcasting) یا مخاطب قرار دادن یک اتاق، یا False برای ارسال به همه به جز فرستنده.
- skip_sid -- شناسه نشست (session id) کلاینتی که هنگام انتشار فراگیر یا مخاطب قرار دادن یک اتاق باید نادیده گرفته شود. این مقدار معمولاً روی مبدا پیام تنظیم میشود تا همه به جز آن کلاینت پیام را دریافت کنند. برای نادیده گرفتن چندین sid یک لیست ارسال کنید.
- callback -- در صورت تعیین، این تابع فراخوانی خواهد شد تا تایید کند که کلاینت پیام را دریافت کرده است. آرگومانهایی که به تابع پاس داده میشوند مواردی هستند که توسط کلاینت فراهم شدهاند. توابع بازخوانی (callback) تنها زمانی میتوانند استفاده شوند که یک کلاینت منفرد مخاطب قرار گیرد.
- call(event, *args, **kwargs)
- ارسال یک
رویداد SocketIO و
انتظار
برای پاسخ.
این متد یک ارسال (emit) را همراه با یک بازخوانی (callback) صادر میکند و پیش از بازگشت، منتظر فراخوانی بازخوانی توسط کلاینت میماند. اگر بازخوانی پیش از مهلت زمانی (timeout) فراخوانی نشود، یک استثنای TimeoutError رخ میدهد. اگر اتصال Socket.IO در طول انتظار قطع شود، این متد همچنان تا پایان مهلت زمانی مشخصشده منتظر میماند. مثال:
def get_status(client, data):
status = call('status', {'data': data}, to=client)
- پارامترها
- event -- نام رویداد کاربری برای ارسال.
- args -- یک دیکشنری شامل دادههای JSON جهت ارسال به عنوان بار داده (payload).
- namespace -- فضای نامی که پیام باید تحت آن ارسال شود. پیشفرض، فضای نام عمومی است.
- to -- شناسه نشست (session ID) کلاینت گیرنده.
- timeout -- مهلت زمانی انتظار. اگر پیش از تایید رویداد توسط کلاینت، مهلت زمانی به پایان برسد، استثنای TimeoutError ایجاد میشود. مقدار پیشفرض 60 ثانیه است.
- ignore_queue -- تنها زمانی استفاده میشود که یک صف پیام (message queue) پیکربندی شده باشد. اگر روی True تنظیم شود، رویداد مستقیماً و بدون عبور از صف به کلاینت ارسال میشود. این حالت کارآمدتر است، اما تنها زمانی کار میکند که از یک فرآیند سرور منفرد استفاده شود، یا زمانی که تنها یک مخاطب وجود داشته باشد. توصیه میشود که این پارامتر را همیشه روی مقدار پیشفرض آن یعنی False باقی بگذارید.
- send(data, json=False, namespace=None, to=None, callback=None, include_self=True, skip_sid=None, **kwargs)
- ارسال یک
پیام SocketIO
تولیدشده
توسط سرور.
این تابع یک پیام ساده SocketIO را به یک یا چند کلاینت متصل ارسال میکند. این پیام میتواند یک رشته یا یک داده ساختاریافته JSON باشد. این نسخه سادهتری از emit() است که اولویت با استفاده از آن میباشد. این تابع میتواند خارج از بافت رویداد SocketIO استفاده شود، بنابراین زمانی که سرور مبدا ایجاد یک رویداد است استفاده از آن مناسب خواهد بود.
- پارامترها
- data -- پیامی که باید ارسال شود؛ به صورت یک رشته متنی یا داده JSON.
- json -- مقدار True اگر message یک داده ساختاریافته JSON باشد، در غیر این صورت False.
- namespace -- فضای نامی که پیام باید تحت آن ارسال شود. پیشفرض، فضای نام عمومی است.
- to -- ارسال پیام به تمام کاربران موجود در اتاق دادهشده، یا به کاربری با شناسه نشست مشخص. اگر این پارامتر مشخص نشود، رویداد به تمام کاربران متصل ارسال میشود.
- include_self -- مقدار True برای گنجاندن فرستنده هنگام انتشار فراگیر یا مخاطب قرار دادن یک اتاق، یا False برای ارسال به همه به جز فرستنده.
- skip_sid -- شناسه نشست کلاینتی که هنگام انتشار فراگیر یا مخاطب قرار دادن یک اتاق باید نادیده گرفته شود. این مقدار معمولاً روی مبدا پیام تنظیم میشود تا همه به جز آن کلاینت پیام را دریافت کنند. برای نادیده گرفتن چندین sid یک لیست پاس دهید.
- callback -- در صورت تعیین، این تابع فراخوانی خواهد شد تا تایید کند که کلاینت پیام را دریافت کرده است. آرگومانهایی که به تابع ارسال میشوند مواردی هستند که توسط کلاینت ارائه شدهاند. توابع بازخوانی تنها زمانی میتوانند استفاده شوند که یک کلاینت به صورت منفرد مخاطب قرار گیرد.
- close_room(room, namespace=None)
- بستن یک
اتاق.
این تابع تمام کاربرانی که در اتاق مشخصشده حضور دارند را حذف کرده و سپس اتاق را از سرور پاک میکند. این تابع میتواند خارج از بافت رویداد SocketIO استفاده شود.
- پارامترها
- room -- نام اتاقی که باید بسته شود.
- namespace -- فضای نامی که اتاق در آن قرار دارد. پیشفرض، فضای نام عمومی است.
- run(app, host=None, port=None, **kwargs)
- اجرای وبسرور SocketIO.
- پارامترها
- app -- نمونه برنامه (instance) مربوط به Flask.
- host -- نام میزبان (hostname) یا آدرس IP که سرور باید روی آن گوش فرا دهد. پیشفرض 127.0.0.1 است..IP • 2 port -- شماره درگاه (پورت) برای گوش دادن کارگزار. پیشفرض 5000 است.
- debug -- مقدار True برای راهاندازی کارگزار در حالت اشکالزدایی، و False برای راهاندازی در حالت عادی.
- use_reloader -- مقدار True برای فعالسازی بارگذار مجدد Flask، و False برای غیرفعال کردن آن.
- reloader_options -- یک دیکشنری از گزینههایی که به بارگذار مجدد Flask ارسال میشوند، مانند extra_files، reloader_type و غیره.
- extra_files -- فهرستی از فایلهای اضافه که بارگذار مجدد Flask باید آنها را زیر نظر بگیرد. پیشفرض None است. منسوخ شده است، به جای آن از reloader_options استفاده کنید.
- log_output -- اگر True باشد، کارگزار تمام اتصالات ورودی را ثبت میکند. اگر False باشد، ثبت وقایع غیرفعال میشود. پیشفرض در حالت اشکالزدایی True و در حالت عادی False است. در صورت استفاده از حالت ناهمگام threading، بلااستفاده خواهد بود.
- allow_unsafe_werkzeug -- تنظیم روی True برای مجاز کردن استفاده از وبسرور Werkzeug در یک محیط عملیاتی. پیشفرض False است. تنظیم روی True با مسئولیت خودتان است.
- kwargs -- گزینههای اضافی وبسرور. گزینههای وبسرور مختص کارگزاری هستند که در هر یک از حالتهای ناهمگام پشتیبانیشده استفاده میشود. توجه داشته باشید گزینههای ارائهشده در اینجا هنگام استفاده از یک وبسرور خارجی مانند gunicorn دیده نخواهند شد، زیرا در آن حالت این متد فراخوانی نمیشود.
- stop()
- متوقف کردن
یک وبسرور
در حال
اجرای SocketIO.
این متد باید از درون یک تابع گرداننده HTTP یا SocketIO فراخوانی شود.
- start_background_task(target, *args, **kwargs)
- شروع یک
وظیفه
پسزمینه
با استفاده
از مدل
ناهمگام
مناسب.
این یک تابع کمکی است که برنامهها میتوانند برای شروع یک وظیفه پسزمینه با استفاده از روشی که با حالت ناهمگامِ انتخابشده سازگار است، از آن استفاده کنند.
- پارامترها (Parameters)
- target -- تابع هدف برای اجرا.
- args -- آرگومانها برای ارسال به تابع.
- kwargs -- آرگومانهای کلیدواژهای برای ارسال به تابع.
این تابع شیئی را بازمیگرداند که نماینده وظیفه پسزمینه است و میتوان متد join() را روی آن فراخوانی کرد تا منتظر تکمیل وظیفه بماند.
- sleep(seconds=0)
- توقف موقت
(خواب) به
میزان زمان
درخواستی
با استفاده
از مدل
ناهمگام
مناسب.
این یک تابع کمکی است که برنامهها میتوانند برای به خواب بردن یک وظیفه، بدون نگرانی درباره استفاده از فراخوانی صحیح برای حالت ناهمگام انتخابشده، از آن استفاده کنند.
- test_client(app, namespace=None, query_string=None, headers=None, auth=None, flask_test_client=None)
- کلاینت آزمایشی Socket.IO برای آزمایش کارگزار Flask-SocketIO مفید است. این کلاینت به شیوهای مشابه با Flask Test Client کار میکند، اما برای کارگزار Socket.IO سازگار شده است.
- پارامترها (Parameters)
- app -- نمونه برنامه Flask.
- namespace -- فضای نام برای کلاینت. در صورت عدم ارائه، کلاینت در فضای نام سراسری (global) به کارگزار متصل میشود.
- query_string -- یک رشته حاوی آرگومانهای سفارشی رشته پرسوجو (query string).
- headers -- یک دیکشنری حاوی سرایندهای سفارشی HTTP.
- auth -- دادههای احراز هویت اختیاری، ارائهشده در قالب یک دیکشنری.
- flask_test_client -- نمونه کلاینت آزمایشی Flask که در حال حاضر استفاده میشود. ارسال کلاینت آزمایشی Flask اختیاری است، اما اگر میخواهید نشست کاربری Flask و هرگونه کوکی دیگرِ تنظیمشده در مسیرهای HTTP از طریق رویدادهای Socket.IO در دسترس باشند، ضروری است.
- flask_socketio.emit(event, *args, **kwargs)
- ارسال (emit) یک
رویداد SocketIO.
این تابع یک رویداد SocketIO را به یک یا چند کلاینت متصل ارسال میکند. یک حباب داده (blob) از نوع JSON میتواند به عنوان بار داده (payload) به رویداد پیوست شود. این تابعی است که تنها میتواند از درون یک گرداننده رویداد SocketIO فراخوانی شود، زیرا برخی اطلاعات را از بافتار (context) کلاینت فعلی به دست میآورد. مثال:
@socketio.on('my event')
def handle_my_custom_event(json):
emit('my response', {'data': 42})
- پارامترها (Parameters)
- event -- نام رویداد کاربر برای ارسال.
- args -- یک دیکشنری با دادههای JSON جهت ارسال به عنوان بار داده (payload).
- namespace -- فضای نامی که پیام باید تحت آن ارسال شود. پیشفرض، فضای نام استفادهشده توسط رویداد مبدا است. از یک '/' میتوان برای مشخص کردن صریح فضای نام سراسری استفاده کرد.
- callback -- تابع بازخوانی (callback) برای فراخوانی همراه با تاییدیه (acknowledgement) کلاینت.
- broadcast -- مقدار True برای ارسال پیام به تمام کلاینتها، یا False برای پاسخ دادن تنها به فرستنده رویداد مبدا.
- to -- ارسال پیام به تمام کاربران حاضر در اتاق مشخصشده، یا به کاربر با شناسه نشست (session ID) مشخصشده. اگر این آرگومان تنظیم نشده باشد و broadcast برابر با False باشد، پیام تنها به کاربر مبدا ارسال میشود.
- include_self -- مقدار True برای در بر گرفتن فرستنده هنگام انتشار همگانی (broadcasting) یا خطاب قرار دادن یک اتاق، یا False برای ارسال به همه به جز فرستنده.
- skip_sid -- شناسه نشست (session id) کلاینتی که هنگام انتشار همگانی یا خطاب قرار دادن یک اتاق باید نادیده گرفته شود. این مقدار معمولاً روی مبدا پیام تنظیم میشود تا همه به جز آن کلاینت پیام را دریافت کنند. برای نادیده گرفتن چندین sid، یک فهرست ارسال کنید.
- ignore_queue -- فقط زمانی استفاده میشود که یک صف پیام (message queue) پیکربندی شده باشد. اگر روی True تنظیم شود، رویداد مستقیماً و بدون عبور از صف به کلاینتها ارسال میشود. این روش کارآمدتر است، اما فقط هنگامی کار میکند که یک فرآیند کارگزار منفرد استفاده شود، یا زمانی که تنها یک گیرنده وجود داشته باشد. توصیه میشود همیشه این پارامتر را با مقدار پیشفرض آن یعنی False رها کنید.
- flask_socketio.send(message, **kwargs)
- ارسال یک پیام SocketIO..sp این تابع یک پیام سادهٔ SocketIO را به یک یا چند کلاینت متصل ارسال میکند. پیام میتواند یک رشته یا یک دادهٔ خام (blob) از نوع JSON باشد. این نسخهٔ سادهتری از emit() است که استفاده از آن ارجحیت دارد. این تابع تنها از درون یک گردانندهٔ رویداد در SocketIO قابل فراخوانی است.
- پارامترها
- message -- پیامی که باید ارسال شود، چه یک رشته یا یک دادهٔ JSON.
- json -- مقدار True اگر message دادهٔ JSON باشد، در غیر این صورت False.
- namespace -- فضای نامی که پیام باید تحت آن ارسال شود. مقدار پیشفرض آن فضای نام استفادهشده توسط رویداد مبدأ است. میتوان از یک رشتهٔ خالی برای استفاده از فضای نام سراسری (global) استفاده کرد.
- callback -- تابع بازفراخوانی (callback) برای فراخوانی همراه با تصدیق دریافت (acknowledgement) کلاینت.
- broadcast -- مقدار True برای ارسال پیام به تمامی کلاینتهای متصل، یا False برای پاسخ دادن تنها به فرستندهٔ رویداد مبدأ.
- to -- ارسال پیام به تمامی کاربران در اتاق مشخصشده، یا به کاربری با شناسهٔ نشست (session ID) دادهشده. اگر این آرگومان تنظیم نشده باشد و broadcast برابر False باشد، پیام تنها به کاربر مبدأ ارسال میشود.
- include_self -- مقدار True برای گنجاندن فرستنده هنگام انتشار همگانی (broadcast) یا مخاطب قرار دادن یک اتاق، یا False برای ارسال به همه به جز فرستنده.
- skip_sid -- شناسهٔ نشست کلاینتی که باید هنگام انتشار همگانی یا مخاطب قرار دادن یک اتاق نادیده گرفته شود. این مقدار معمولاً روی شناسهٔ مبدأ پیام تنظیم میشود تا همه به جز آن کلاینت پیام را دریافت کنند. برای نادیده گرفتن چندین sid، یک فهرست (list) پاس دهید.
- ignore_queue -- تنها زمانی استفاده میشود که یک صف پیام (message queue) پیکربندی شده باشد. اگر روی True تنظیم شود، رویداد مستقیماً و بدون عبور از صف برای کلاینتها ارسال میشود. این کارایی بالاتری دارد، اما فقط زمانی کار میکند که یک فرایند سرور منفرد استفاده شده باشد، یا فقط یک مخاطب وجود داشته باشد. توصیه میشود همیشه این پارامتر را روی مقدار پیشفرض False رها کنید.
- flask_socketio.join_room(room, sid=None, namespace=None)
- پیوستن به
یک اتاق.
این تابع کاربر را در یک اتاق، تحت فضای نام فعلی قرار میدهد. کاربر و فضای نام از بافتار رویداد (event context) به دست میآیند. این تابعی است که تنها میتواند از درون یک گردانندهٔ رویداد در SocketIO فراخوانی شود. مثال:
@socketio.on('join')
def on_join(data):
username = session['username']
room = data['room']
join_room(room)
send(username + ' has entered the room.', to=room)
- پارامترها
- room -- نام اتاقی که باید به آن پیوست.
- sid -- شناسهٔ نشست کلاینت. در صورت عدم ارائه، کلاینت از بافتار درخواست (request context) به دست میآید.
- namespace -- فضای نام برای اتاق. در صورت عدم ارائه، فضای نام از بافتار درخواست به دست میآید.
- flask_socketio.leave_room(room, sid=None, namespace=None)
- ترک یک
اتاق.
این تابع کاربر را از یک اتاق، تحت فضای نام فعلی خارج میکند. کاربر و فضای نام از بافتار رویداد به دست میآیند. مثال:
@socketio.on('leave')
def on_leave(data):
username = session['username']
room = data['room']
leave_room(room)
send(username + ' has left the room.', to=room)
- پارامترها
- room -- نام اتاقی که باید ترک شود.
- sid -- شناسهٔ نشست کلاینت. در صورت عدم ارائه، کلاینت از بافتار درخواست به دست میآید.
- namespace -- فضای نام برای اتاق. در صورت عدم ارائه، فضای نام از بافتار درخواست به دست میآید.
- flask_socketio.close_room(room, namespace=None)
- بستن یک
اتاق.
این تابع تمامی کاربران حاضر در اتاق دادهشده را خارج کرده و سپس اتاق را از روی سرور حذف میکند.
- پارامترها
- room -- نام اتاقی که باید بسته شود.
- namespace -- فضای نام برای اتاق. در صورت عدم ارائه، فضای نام از بافتار درخواست به دست میآید.
- flask_socketio.rooms(sid=None, namespace=None)
- بازگرداندن
فهرستی از
اتاقهایی
که کلاینت
در آنها
حضور دارد.
این تابع تمامی اتاقهایی را که کلاینت وارد آنها شده است بازمیگرداند، از جمله اتاق اختصاصی خودش که توسط سرور Socket.IO اختصاص یافته است.
- پارامترها
- sid -- شناسهٔ نشست کلاینت. در صورت عدم ارائه، کلاینت از بافتار درخواست به دست میآید.
- namespace -- فضای نام برای اتاق. در صورت عدم ارائه، فضای نام از بافتار درخواست به دست میآید.
- flask_socketio.disconnect(sid=None, namespace=None, silent=False)
- قطع اتصال
کلاینت.
این تابع اتصال با کلاینت را خاتمه میدهد. در نتیجهٔ این فراخوانی، کلاینت یک رویداد disconnect دریافت خواهد کرد. مثال:
@socketio.on('message')
def receive_message(msg):
if is_banned(session['username']):
disconnect()
else:
# ...
- sid -- شناسه نشست کلاینت. در صورت عدم ارائه، کلاینت از بافتار درخواست (request context) دریافت میشود.
- namespace -- فضاینام برای اتاق. در صورت عدم ارائه، فضاینام از بافتار درخواست دریافت میشود.
- silent -- این گزینه منسوخ شده است.
- trigger_event(event, *args)
- ارسال یک
رویداد به
متد
گرداننده (handler)
مناسب.
در رایجترین حالت استفاده، این متد توسط زیرکلاسها بازنویسی (overload) نمیشود، زیرا مسیریابی رویدادها به متدها را انجام میدهد. با این حال، در صورتی که به قوانین ارسال (dispatching) سفارشی نیاز باشد، یا داشتن یک متد واحد که تمام رویدادها را دریافت کند مد نظر باشد، میتوان این متد را بازنویسی (override) کرد.
- emit(event, data=None, room=None, include_self=True, namespace=None, callback=None)
- انتشار یک رویداد سفارشی به یک یا چند کلاینت متصل.
- send(data, room=None, include_self=True, namespace=None, callback=None)
- ارسال یک پیام به یک یا چند کلاینت متصل.
- close_room(room, namespace=None)
- بستن یک اتاق.
- class flask_socketio.SocketIOTestClient(app, socketio, namespace=None, query_string=None, headers=None, auth=None, flask_test_client=None)
- این کلاس برای آزمایش سرور Flask-SocketIO مفید است. این کلاس به روشی مشابه با کلاینت آزمایشی Flask کار میکند، اما برای سرور Socket.IO تطبیق داده شده است.
- پارامترها
- app -- نمونه برنامه Flask.
- socketio -- نمونه SocketIO برنامه.
- namespace -- فضاینام کلاینت. در صورت عدم ارائه، کلاینت در فضاینام سراسری (global) به سرور متصل میشود.
- query_string -- یک رشته شامل آرگومانهای سفارشی رشته پرسوجو (query string).
- headers -- یک دیکشنری شامل سرآیندهای (headers) سفارشی HTTP.
- auth -- دادههای احراز هویت اختیاری، ارائه شده در قالب یک دیکشنری.
- flask_test_client -- نمونه کلاینت آزمایشی Flask که در حال حاضر استفاده میشود. ارسال کلاینت آزمایشی Flask اختیاری است، اما اگر میخواهید نشست کاربری Flask و سایر کوکیهای تنظیمشده در مسیرهای HTTP از طریق رویدادهای Socket.IO قابل دسترسی باشند، ضروری است.
- is_connected(namespace=None)
- بررسی متصل بودن یک فضاینام.
- پارامترها
- namespace -- فضاینام برای بررسی. در صورت عدم ارائه این آرگومان، فضاینام سراسری فرض میشود.
- connect(namespace=None, query_string=None, headers=None, auth=None)
- متصل کردن کلاینت.
- پارامترها
- namespace -- فضاینام برای کلاینت. در صورت عدم ارائه، کلاینت در فضاینام سراسری به سرور متصل میشود.
- query_string -- یک رشته شامل آرگومانهای سفارشی رشته پرسوجو (query string).
- headers -- یک دیکشنری شامل سرآیندهای سفارشی HTTP.
- auth -- دادههای احراز هویت اختیاری، ارائه شده در قالب یک دیکشنری.
توجه داشته باشید که معمولاً فراخوانی صریح این متد ضروری نیست، زیرا هنگام ایجاد یک نمونه از این کلاس، اتصال به طور خودکار برقرار میشود. یک مثال که در آن این متد مفید خواهد بود زمانی است که برنامه اتصالات چندگانه فضاینام را بپذیرد.
- disconnect(namespace=None)
- قطع اتصال کلاینت.
- پارامترها
- namespace -- فضاینام برای قطع اتصال. در صورت عدم ارائه این آرگومان، فضاینام سراسری فرض میشود.
- emit(event, *args, **kwargs)
- انتشار یک رویداد به سرور.
- پارامترها
- event -- نام رویداد.
- *args --
آرگومانهای رویداد.
- callback -- مقدار True اگر کلاینت درخواست کالبک (callback) داشته باشد، و در غیر این صورت False. توجه داشته باشید که کالبکهای سمت کلاینت پیادهسازی نشدهاند؛ یک درخواست کالبک صرفاً به سرور اعلام میکند که آرگومانهای لازم برای فراخوانی کالبک را ارسال کند، اما هیچ کالبکی فراخوانی نمیشود. در عوض، آرگومانهایی که سرور برای کالبک ارائه کرده است توسط این تابع بازگردانده میشوند.
- namespace -- فضاینام رویداد. در صورت عدم ارائه این آرگومان، فضاینام سراسری فرض میشود.
- send(data, json=False, callback=False, namespace=None)
- ارسال یک پیام متنی یا JSON به سرور.
- پارامترها
- data -- یک رشته، دیکشنری یا لیست برای ارسال به سرور.
- json -- مقدار True برای ارسال یک پیام JSON، و False برای ارسال یک پیام متنی.
- callback -- مقدار True اگر کلاینت درخواست کالبک (callback) داشته باشد، و در غیر این صورت False. توجه داشته باشید که کالبکهای سمت کلاینت پیادهسازی نشدهاند؛ یک درخواست کالبک صرفاً به سرور اعلام میکند که آرگومانهای لازم برای فراخوانی کالبک را ارسال کند، اما هیچ کالبکی فراخوانی نمیشود. در عوض، آرگومانهایی که سرور برای کالبک ارائه کرده است توسط این تابع بازگردانده میشوند.
- namespace -- فضاینام رویداد. در صورت عدم ارائه این آرگومان، فضاینام سراسری فرض میشود.
- get_received(namespace=None)
- بازگرداندن فهرست پیامهای دریافت شده از سرور..sp از آنجا که این یک کلاینت واقعی نیست، هر زمان که سرور رویدادی را ارسال کند، رویداد صرفاً ذخیره میشود. کد تست میتواند این متد را فراخوانی کند تا فهرست رویدادهایی را که از زمان آخرین فراخوانی دریافت شدهاند، به دست آورد.
- پارامترها
- namespace -- فضای نام برای دریافت رویدادها از آن. در صورتی که این آرگومان مشخص نشود، فضای نام سراسری (global) فرض میشود.
- نمایه <>
- نمایه ماژول <>
- صفحه جستجو <>
نویسندگان (AUTHORS)
Miguel Grinberg
کپیرایت و تکثیر (COPYRIGHT)
2018, Miguel Grinberg
| March 14, 2026 |