├── .gitignore
├── LICENSE
├── README.md
├── django_socketio
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
├── fr
└── README.md
├── manage.py
├── requirements.txt
└── socketio_app
├── __init__.py
├── admin.py
├── apps.py
├── migrations
└── __init__.py
├── models.py
├── static
└── index.html
├── tests.py
├── urls.py
└── views.py
/.gitignore:
--------------------------------------------------------------------------------
1 | log.txt
2 |
3 | .DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | ._*
8 |
9 |
10 | .Spotlight-V100
11 | .Trashes
12 |
13 | .AppleDB
14 | .AppleDesktop
15 | .apdisk
16 |
17 |
18 | __pycache__/
19 | *.py[cod]
20 |
21 | *.so
22 |
23 | .Python
24 | env/
25 | build/
26 | develop-eggs/
27 | dist/
28 | downloads/
29 | eggs/
30 | lib/
31 | lib64/
32 | parts/
33 | sdist/
34 | var/
35 | *.egg-info/
36 | .installed.cfg
37 | *.egg
38 |
39 |
40 | *.manifest
41 | *.spec
42 |
43 | pip-log.txt
44 | pip-delete-this-directory.txt
45 |
46 |
47 | htmlcov/
48 | .tox/
49 | .coverage
50 | .cache
51 | nosetests.xml
52 | coverage.xml
53 |
54 | *.mo
55 | *.pot
56 |
57 | docs/_build/
58 |
59 | target/
60 |
61 |
62 | *.log
63 | *.pot
64 | *.pyc
65 | __pycache__/
66 | local_settings.py
67 |
68 | .env
69 | db.sqlite3
70 |
71 | staticfiles/
72 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Miguel Grinberg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # python-socket.io-django
2 | 
3 | 
4 | 
5 |
6 | Raw socket.io integration in a django server.
7 |
8 |
9 | - French version is [here](https://github.com/mokira3d48/python-socket.io-django/tree/master/fr)
10 |
11 |
12 |
13 |
14 | ## Prérequis
15 |
16 | Vous devez installer `python version 3.8.10 ou plus` sur votre machine.
17 | Sous Ubuntu :
18 |
19 | ```
20 | sudo apt install python3
21 | ```
22 | Sous certaines distributions linux,
23 | ```
24 | sudo apt install python
25 | ```
26 |
27 |
28 |
29 | PS : Si vous verifiez la version et qu'elle n'est la bonne `3.8.10 ou plus`, alors cherchez comment installer ou mettre
30 | à jour ce qui a été installé.
31 |
32 |
33 |
34 | Ensuite, installer le gestionnaire de dépendance `pip3` pour python3.
35 | Sous Ubuntu :
36 |
37 | ```
38 | sudo apt install python3-pip
39 | ```
40 |
41 |
42 |
43 |
44 |
45 | ## Version de python
46 | Exécutez la ligne de commande suivante pour vérifier votre version de `python`.
47 | ```
48 | python --version
49 | ```
50 | PS : Pour ceux qui sont sur certain système `Linux` notamment `Ubuntu`, exécuter plutôt la ligne de commande suivante :
51 | ```
52 | python3 --version
53 | ```
54 |
55 | Chez moi en ce moment, ma version de python est `3.8.10`.
56 | ```
57 | Python 3.8.10
58 | ```
59 | Je vous recommande d'avoir cette version ou une version supérieur à celle-ci.
60 |
61 |
62 |
63 |
64 | ## Configuration d'un environnement virtuel
65 |
66 | Avant d'installer les modules, il faut créer un environnement virtuel. C'est dans ce dernier, qu'on va
67 | installer les différents modules du serveur.
68 |
69 |
70 |
71 | ### Installation de virtualenv
72 |
73 | On va utiliser `virtualenv` pour créer un environnement virtuel.
74 |
75 | ```
76 | sudo pip3 install virtualenv
77 | ```
78 |
79 | Ensuite, dans le dossier du projet, créer un environement virtuel en tapant la commande suivante :
80 |
81 | ```
82 | python3 -m venv env
83 | ```
84 |
85 |
86 | ### Activation de l'environnement
87 | Enfin, on active l'environement virtuel
88 |
89 | ```
90 | source env/bin/activate
91 | ```
92 |
93 | Si tous va bien, on peut passer à l'installation des modules.
94 |
95 |
96 |
97 |
98 | ## Installation des modules
99 | Voici tous les modules dont on a besoin pour monter notre serveur socket.
100 |
101 | Contenu du fichier `requirements.txt` :
102 |
103 | ```
104 | asgiref==3.4.1
105 | bidict==0.21.2
106 | Django==3.2.6
107 | dnspython==1.16.0
108 | enum-compat==0.0.3
109 | eventlet==0.30.0
110 | gevent==21.1.2
111 | gevent-websocket==0.10.1
112 | greenlet==0.4.17
113 | python-engineio==4.2.1
114 | python-socketio==5.4.0
115 | pytz==2021.1
116 | six==1.10.0
117 | sqlparse==0.4.1
118 | zope.event==4.5.0
119 | zope.interface==5.4.0
120 |
121 | ```
122 | Utiliser la commande suivante pour installer tous les modules contenus dans le fichier.
123 | Vous pouvez aussi les installer un a un afin d'avoir leur dernière version.
124 |
125 | ```
126 | pip install -r requirements.txt
127 | ```
128 |
129 |
130 |
131 | ## Creation d'un projet Django
132 | On va maintenant créer un projet Django nommé `django_socketio` par exemple.
133 |
134 | ```
135 | django-admin startproject django_socketio
136 | ```
137 |
138 | Il faut créer ensuite une application. C'est dans cette dernière qu'on va implémenter un exemple de programme de chat pour tester notre serveur de `socket.io`.
139 |
140 | ```
141 | django-admin startapp socketio_app
142 | ```
143 |
144 |
145 |
146 | ## Configuration du projet
147 | On va placer les boûts de code qu'il faut dans certains fichiers de django.
148 |
149 |
150 | ### Configuration de l'URL
151 | 1. Dans le fichier `django_socketio/urls.py`, insérer la ligne suivante :
152 |
153 | ```python
154 | from django.conf.urls import url, include
155 |
156 | # ...
157 | ```
158 |
159 | ensuite,
160 |
161 | ```python
162 | # ...
163 |
164 | urlpatterns = [
165 | url(r'', include('socketio_app.urls')),
166 | path('admin/', admin.site.urls),
167 | ]
168 | ```
169 |
170 |
171 |
172 | 2. Dans le dossier `django_socketio/socketio_app/`, créez le fichier `urls.py` et insérer s'y
173 | le code suivant :
174 |
175 | ```python
176 | from django.conf.urls import url
177 |
178 | from . import views
179 |
180 | urlpatterns = [
181 | url(r'', views.index, name='index'),
182 | ];
183 |
184 | ```
185 |
186 |
187 | ### Configuration du serveur en socket.io
188 | On va maintenant mettre en place les fonctionnalités du serveur de socket.io.
189 |
190 | 1. Dans le fichier `django_socketio/socketio_app/views.py` insérer les lignes de code suivantes :
191 |
192 | ```python
193 | import socketio
194 |
195 | # mode d'asynchronisation
196 | async_mode = 'gevent';
197 |
198 | # definition du serveur de socket.io
199 | sio = socketio.Server(async_mode=async_mode);
200 |
201 |
202 | ```
203 |
204 |
205 |
206 | 
207 |
208 | - Le déploiement est délicat, car les sockets ne sont pas basés sur le protocole HTTP. Le serveur d'applications alloue généralement un processus ou un fil distinct pour chaque demande. Par conséquent, nous devons utiliser `Gevent`, qui agit comme une boucle d'événements et chaque fois qu'il y a une demande de connexion, il génère un nouveau thread et attribue la connexion à ce thread.
209 |
210 | - Nous avons décidé de séparer l'application socket de l'application normale, car la prise en charge à la fois de la fonction Django normale et de l'application socket dans une seule `application Django` rendait la gestion des réponses aux requêtes lente.
211 |
212 | - Le déplacement du code socketio vers une autre application a également facilité la maintenance du code.
213 |
214 | Par [ici](https://www.botreetechnologies.com/blog/django-websocket-with-socketio/) pour en savoir plus.
215 |
216 |
217 |
218 |
219 | 2. Remplacez les lignes de code du fichier `django_socketio/wsgi.py` par les suivantes :
220 |
221 | ```python
222 | import os
223 | import socketio
224 |
225 | from django.core.wsgi import get_wsgi_application
226 | from socketio_app.views import sio
227 |
228 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_socketio.settings');
229 |
230 | django_app = get_wsgi_application();
231 | application = socketio.WSGIApp(sio, django_app);
232 |
233 | ####################################################################################
234 |
235 | from gevent import pywsgi
236 | from geventwebsocket.handler import WebSocketHandler
237 |
238 | server = pywsgi.WSGIServer(("", 8000), application, handler_class=WebSocketHandler);
239 | server.serve_forever();
240 |
241 | ```
242 |
243 |
244 |
245 | ## Implémentation des exemples de fonctionnalités avec socket.io
246 | On va mettre en place le programme serveur et un programme client.
247 |
248 | ### Programme serveur
249 |
250 | On va juste essayer d'implémenter un programme de chat. Remplacez donc tous le code contenu dans le fichier `django_socketio/socketio_app/views.py` par les lignes de code suivantes :
251 |
252 | ```python
253 | # définissez async_mode sur 'threading', 'eventlet', 'gevent' ou 'gevent_uwsgi' sur
254 | # forcer un autre mode, le meilleur mode est sélectionné automatiquement parmi ce qui est
255 | # installée
256 | sync_mode = 'gevent';
257 |
258 | import os
259 |
260 | from django.http import HttpResponse
261 | import socketio
262 |
263 | basedir = os.path.dirname(os.path.realpath(__file__));
264 | sio = socketio.Server(async_mode=async_mode);
265 |
266 | # thread = None
267 | users = {};
268 |
269 | def index(request):
270 | """
271 | Programme qui permet de renvoiyer la page web `index`
272 | """
273 |
274 | # global thread;
275 |
276 | # if thread is None:
277 | # thread = sio.start_background_task(background_thread);
278 |
279 | return HttpResponse(open(os.path.join(basedir, 'static/index.html')));
280 |
281 |
282 | # def background_thread():
283 | # """ Exemple de programme d'execution de programme d'arriere plan """
284 |
285 | # count = 0;
286 |
287 | # while True:
288 | # sio.sleep(10);
289 | # count += 1;
290 | # sio.emit('my_response', {'data': 'Server generated event'}, namespace='/test');
291 |
292 | @sio.event
293 | def set_username(sid, message):
294 | """ Programme de modification du nom d'utilisateur """
295 | users[sid] = message['data'];
296 |
297 | # on notifit que le username a ete correctement notifie
298 | sio.emit('my_response', {'data': f"Username is set to {users[sid]} !"}, to=sid);
299 |
300 |
301 |
302 | @sio.event
303 | def my_event(sid, message):
304 | # Programme qui permet d'envoyer le message a moi meme
305 | sio.emit('my_response', {'data': message['data']}, room=sid);
306 |
307 |
308 |
309 | @sio.event
310 | def my_broadcast_event(sid, message):
311 | # Programme qui permet d'envoyer le message a tous le monde
312 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"});
313 |
314 |
315 |
316 | @sio.event
317 | def join(sid, message):
318 | """ Programme de creation et d'adesion de canale """
319 |
320 | # on cree le canale et on se join a ce canal
321 | sio.enter_room(sid, message['room']);
322 |
323 | # sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, room=sid);
324 |
325 | # on emet a tous ceux qui sont dans le canal qu'on de
326 | # rejoindre le canal
327 | sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, to=message['room']);
328 |
329 |
330 | @sio.event
331 | def leave(sid, message):
332 | """ Programme de deconnection d'un canal """
333 |
334 | # on se deconnecte du canal
335 | sio.leave_room(sid, message['room']);
336 |
337 | # on informe tous ceux qui sont dans le canal, que celui-ci
338 | # a quitte le canal
339 | sio.emit('my_response', {'data': users[sid] + ' left room: ' + message['room']}, room=message['room']);
340 |
341 |
342 | @sio.event
343 | def close_room(sid, message):
344 | """ Programme de fermeture d'un canal """
345 |
346 | # on ferme le canal
347 | sio.close_room(message['room']);
348 | sio.emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.'}, room=message['room']);
349 |
350 |
351 | @sio.event
352 | def my_room_event(sid, message):
353 | """ Programme qui permet d'envoyer un message a tous les membres du canal """
354 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"}, room=message['room']);
355 |
356 |
357 | @sio.event
358 | def disconnect_request(sid):
359 | """ Programme qui declanche la deconnection de l'utilisateur """
360 | sio.disconnect(sid);
361 |
362 |
363 | @sio.event
364 | def connect(sid, environ):
365 | """ Programme de connexion
366 | Au cour de la connexion, on enregistre tous les utilisateurs
367 | connectes
368 | """
369 |
370 | print(f"{sid}\t connected");
371 |
372 | # on ajoute le nouveau a la liste
373 | users[sid] = None;
374 |
375 | # on lui notifie qu'il s'est bien connecte
376 | sio.emit('my_response', {'data': 'Connected', 'count': len(users)}, room=sid);
377 |
378 | # on notifie a tous le monde le nombre de personnes actuellement connectes
379 | sio.emit('my_response', {'data': f'{len(users)} connected now!', 'count': len(users)});
380 |
381 |
382 | @sio.event
383 | def disconnect(sid):
384 | """ Programme de deconnexion
385 | Lors de la deconnexion, on supprime l'utilisateur de la liste des
386 | connectes
387 | """
388 |
389 | print(f"{sid}\t {users[sid]} disconnected");
390 |
391 | # on notifie a tous le monde le nombre de personnes actuellement connectes
392 | sio.emit('my_response', {'data': f"{users[sid]} is disconnected", 'count': len(users)});
393 |
394 | # on le supprime de la liste
395 | del users[sid];
396 |
397 | # on notifie a tous le monde le nombre de personnes actuellement connectes
398 | sio.emit('my_response', {'data': f'{len(users)} connected', 'count': len(users)});
399 |
400 |
401 | ```
402 |
403 | ### Programme client
404 | En effet, il s'agit de mettre en place une interface WEB.
405 | Dans le dossier `django_socketio/socketio_app/`, créez un dossier nommé `static`, ensuite, dans ce dernier, créer un fichier nommé `index.html`. Dans ce fichier, insérez les lignes de code suivantes :
406 |
407 | ```html
408 |
409 |
410 |
411 | Django + SocketIO Test
412 |
413 |
414 |
466 |
467 |
468 | Django + SocketIO Test
469 | Send:
470 |
474 |
478 |
482 |
486 |
490 |
495 |
499 |
502 | Receive:
503 |
504 |
505 |
506 |
507 | ```
508 |
509 |
510 |
511 | ## Démarrage du serveur
512 | N'oublier pas de sauvegarder tous les fichiers sources. Il est temps de tester notre programme.
513 | On doit d'abord faire un migration dans une base de données avant de démarrer le serveur.
514 | Pour faire la migration, tappez la commande suivante :
515 |
516 | ```
517 | ./manage.py migrate
518 | ```
519 |
520 | On peut maintenant démarrer le serveur avec la commande suivante :
521 |
522 | ```
523 | ./manage.py runserver
524 | ```
525 |
526 | Si tout va bien, vous verrez le message suivant affichez dans votre terminal.
527 |
528 | ```
529 | Watching for file changes with StatReloader
530 | Performing system checks...
531 |
532 | System check identified no issues (0 silenced).
533 | August 30, 2021 - 01:55:05
534 | Django version 3.2.6, using settings 'django_socketio.settings'
535 | Starting development server at http://127.0.0.1:8000/
536 | Quit the server with CONTROL-C.
537 | ```
538 |
539 |
540 |
541 | ## Test
542 | Voici le lien pour accéder à l'interface web : [http://127.0.0.1:8000/](http://127.0.0.1:8000/).
543 | Pour que d'autre ordinateur puisse accéder à votre application, il faut qu'ils soient dans le même réseau que votre ordinateur. Ensuite, ils doivent utiliser votre adresse IP (souvent sous la forme `192.168.xxx.xxx`). Pour connaitre votre adresse IP :
544 |
545 | - sous linux :
546 |
547 | ```
548 | sudo ifconfig
549 | ```
550 |
551 | - sous windows :
552 |
553 | ```
554 | ipconfig
555 | ```
556 | Ensuite rendez-vous dans le fichier `django_socketio/settings.py` pour permettre l'accès au serveur via cet adresse IP. Si par exemple mon adresse IP est `192.168.100.31`, alors vous devez modifier la ligne de code suivante dans le fichier `django_socketio/settings.py`
557 |
558 | ```python
559 | # ...
560 |
561 | ALLOWED_HOSTS = ['192.168.100.31'];
562 |
563 | # La ligne ci-dessus permettra au autre ordinateur qui sont sur le même réseau que moi
564 | # de pouvoir accéder à mon serveur socket.io via le lien http://192.168.100.31:8000/
565 |
566 | # ...
567 | ```
568 |
569 |
570 |
571 |
572 | ## Système d'exploitation
573 |
574 | ```
575 | Kernel: 5.8.0-59-generic x86_64 bits: 64 compiler: N/A Desktop: Gnome 3.36.9
576 | Distro: Ubuntu 20.04.2 LTS (Focal Fossa)
577 | ```
578 |
579 |
580 |
--------------------------------------------------------------------------------
/django_socketio/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mokira3d48/python-socket.io-django/c6495f692c7915c00163e3cb19c85d9a9a17bf3d/django_socketio/__init__.py
--------------------------------------------------------------------------------
/django_socketio/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for django_socketio project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_socketio.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/django_socketio/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for django_socketio project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.5.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'django-insecure-ie=_%as-#k!0^%sxe)^jce#ikpu31z*o_k@-6f(@bh%@dcdsfz'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = [];
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'socketio_app',
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | 'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'django_socketio.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [],
59 | 'APP_DIRS': True,
60 | 'OPTIONS': {
61 | 'context_processors': [
62 | 'django.template.context_processors.debug',
63 | 'django.template.context_processors.request',
64 | 'django.contrib.auth.context_processors.auth',
65 | 'django.contrib.messages.context_processors.messages',
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = 'django_socketio.wsgi.application'
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
76 |
77 | DATABASES = {
78 | 'default': {
79 | 'ENGINE': 'django.db.backends.sqlite3',
80 | 'NAME': BASE_DIR / 'db.sqlite3',
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91 | },
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
106 |
107 | LANGUAGE_CODE = 'en-us'
108 |
109 | TIME_ZONE = 'UTC'
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
120 |
121 | STATIC_URL = '/static/'
122 |
123 | # Default primary key field type
124 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
125 |
126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
127 |
--------------------------------------------------------------------------------
/django_socketio/urls.py:
--------------------------------------------------------------------------------
1 | """django_socketio URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import url, include
17 | from django.contrib import admin
18 | from django.urls import path
19 |
20 |
21 | urlpatterns = [
22 | url(r'', include('socketio_app.urls')),
23 | path('admin/', admin.site.urls),
24 | ]
25 |
--------------------------------------------------------------------------------
/django_socketio/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for django_socketio project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 | import socketio
12 |
13 | from django.core.wsgi import get_wsgi_application
14 | from socketio_app.views import sio
15 |
16 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_socketio.settings');
17 |
18 | django_app = get_wsgi_application();
19 | application = socketio.WSGIApp(sio, django_app);
20 |
21 | ####################################################################################
22 |
23 | from gevent import pywsgi
24 | from geventwebsocket.handler import WebSocketHandler
25 |
26 | server = pywsgi.WSGIServer(("", 8000), application, handler_class=WebSocketHandler);
27 | server.serve_forever();
28 |
29 |
--------------------------------------------------------------------------------
/fr/README.md:
--------------------------------------------------------------------------------
1 | # python-socket.io-django
2 | Exemple de programme `python` de `socket.io` avec le framework `Django`.
3 |
4 |
5 |
6 |
7 | ## Prérequis
8 |
9 | Vous devez installer `python version 3.8.10 ou plus` sur votre machine.
10 | Sous Ubuntu :
11 |
12 | ```
13 | sudo apt install python3
14 | ```
15 | Sous certaines distributions linux,
16 | ```
17 | sudo apt install python
18 | ```
19 |
20 |
21 |
22 | PS : Si vous verifiez la version et qu'elle n'est la bonne `3.8.10 ou plus`, alors cherchez comment installer ou mettre
23 | à jour ce qui a été installé.
24 |
25 |
26 |
27 | Ensuite, installer le gestionnaire de dépendance `pip3` pour python3.
28 | Sous Ubuntu :
29 |
30 | ```
31 | sudo apt install python3-pip
32 | ```
33 |
34 |
35 |
36 |
37 |
38 | ## Version de python
39 | Exécutez la ligne de commande suivante pour vérifier votre version de `python`.
40 | ```
41 | python --version
42 | ```
43 | PS : Pour ceux qui sont sur certain système `Linux` notamment `Ubuntu`, exécuter plutôt la ligne de commande suivante :
44 | ```
45 | python3 --version
46 | ```
47 |
48 | Chez moi en ce moment, ma version de python est `3.8.10`.
49 | ```
50 | Python 3.8.10
51 | ```
52 | Je vous recommande d'avoir cette version ou une version supérieur à celle-ci.
53 |
54 |
55 |
56 |
57 | ## Configuration d'un environnement virtuel
58 |
59 | Avant d'installer les modules, il faut créer un environnement virtuel. C'est dans ce dernier, qu'on va
60 | installer les différents modules du serveur.
61 |
62 |
63 |
64 | ### Installation de virtualenv
65 |
66 | On va utiliser `virtualenv` pour créer un environnement virtuel.
67 |
68 | ```
69 | sudo pip3 install virtualenv
70 | ```
71 |
72 | Ensuite, dans le dossier du projet, créer un environement virtuel en tapant la commande suivante :
73 |
74 | ```
75 | python3 -m venv env
76 | ```
77 |
78 |
79 | ### Activation de l'environnement
80 | Enfin, on active l'environement virtuel
81 |
82 | ```
83 | source env/bin/activate
84 | ```
85 |
86 | Si tous va bien, on peut passer à l'installation des modules.
87 |
88 |
89 |
90 |
91 | ## Installation des modules
92 | Voici tous les modules dont on a besoin pour monter notre serveur socket.
93 |
94 | Contenu du fichier `requirements.txt` :
95 |
96 | ```
97 | asgiref==3.4.1
98 | bidict==0.21.2
99 | Django==3.2.6
100 | dnspython==1.16.0
101 | enum-compat==0.0.3
102 | eventlet==0.30.0
103 | gevent==21.1.2
104 | gevent-websocket==0.10.1
105 | greenlet==0.4.17
106 | python-engineio==4.2.1
107 | python-socketio==5.4.0
108 | pytz==2021.1
109 | six==1.10.0
110 | sqlparse==0.4.1
111 | zope.event==4.5.0
112 | zope.interface==5.4.0
113 |
114 | ```
115 | Utiliser la commande suivante pour installer tous les modules contenus dans le fichier.
116 | Vous pouvez aussi les installer un a un afin d'avoir leur dernière version.
117 |
118 | ```
119 | pip install -r requirements.txt
120 | ```
121 |
122 |
123 |
124 | ## Creation d'un projet Django
125 | On va maintenant créer un projet Django nommé `django_socketio` par exemple.
126 |
127 | ```
128 | django-admin startproject django_socketio
129 | ```
130 |
131 | Il faut créer ensuite une application. C'est dans cette dernière qu'on va implémenter un exemple de programme de chat pour tester notre serveur de `socket.io`.
132 |
133 | ```
134 | django-admin startapp socketio_app
135 | ```
136 |
137 |
138 |
139 | ## Configuration du projet
140 | On va placer les boûts de code qu'il faut dans certains fichiers de django.
141 |
142 |
143 | ### Configuration de l'URL
144 | 1. Dans le fichier `django_socketio/urls.py`, insérer la ligne suivante :
145 |
146 | ```python
147 | from django.conf.urls import url, include
148 |
149 | # ...
150 | ```
151 |
152 | ensuite,
153 |
154 | ```python
155 | # ...
156 |
157 | urlpatterns = [
158 | url(r'', include('socketio_app.urls')),
159 | path('admin/', admin.site.urls),
160 | ]
161 | ```
162 |
163 |
164 |
165 | 2. Dans le dossier `django_socketio/socketio_app/`, créez le fichier `urls.py` et insérer s'y
166 | le code suivant :
167 |
168 | ```python
169 | from django.conf.urls import url
170 |
171 | from . import views
172 |
173 | urlpatterns = [
174 | url(r'', views.index, name='index'),
175 | ];
176 |
177 | ```
178 |
179 |
180 | ### Configuration du serveur en socket.io
181 | On va maintenant mettre en place les fonctionnalités du serveur de socket.io.
182 |
183 | 1. Dans le fichier `django_socketio/socketio_app/views.py` insérer les lignes de code suivantes :
184 |
185 | ```python
186 | import socketio
187 |
188 | # mode d'asynchronisation
189 | async_mode = 'gevent';
190 |
191 | # definition du serveur de socket.io
192 | sio = socketio.Server(async_mode=async_mode);
193 |
194 |
195 | ```
196 |
197 |
198 |
199 | 
200 |
201 | - Le déploiement est délicat, car les sockets ne sont pas basés sur le protocole HTTP. Le serveur d'applications alloue généralement un processus ou un fil distinct pour chaque demande. Par conséquent, nous devons utiliser `Gevent`, qui agit comme une boucle d'événements et chaque fois qu'il y a une demande de connexion, il génère un nouveau thread et attribue la connexion à ce thread.
202 |
203 | - Nous avons décidé de séparer l'application socket de l'application normale, car la prise en charge à la fois de la fonction Django normale et de l'application socket dans une seule `application Django` rendait la gestion des réponses aux requêtes lente.
204 |
205 | - Le déplacement du code socketio vers une autre application a également facilité la maintenance du code.
206 |
207 | Par [ici](https://www.botreetechnologies.com/blog/django-websocket-with-socketio/) pour en savoir plus.
208 |
209 |
210 |
211 |
212 | 2. Remplacez les lignes de code du fichier `django_socketio/wsgi.py` par les suivantes :
213 |
214 | ```python
215 | import os
216 | import socketio
217 |
218 | from django.core.wsgi import get_wsgi_application
219 | from socketio_app.views import sio
220 |
221 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_socketio.settings');
222 |
223 | django_app = get_wsgi_application();
224 | application = socketio.WSGIApp(sio, django_app);
225 |
226 | ####################################################################################
227 |
228 | from gevent import pywsgi
229 | from geventwebsocket.handler import WebSocketHandler
230 |
231 | server = pywsgi.WSGIServer(("", 8000), application, handler_class=WebSocketHandler);
232 | server.serve_forever();
233 |
234 | ```
235 |
236 |
237 |
238 | ## Implémentation des exemples de fonctionnalités avec socket.io
239 | On va mettre en place le programme serveur et un programme client.
240 |
241 | ### Programme serveur
242 |
243 | On va juste essayer d'implémenter un programme de chat. Remplacez donc tous le code contenu dans le fichier `django_socketio/socketio_app/views.py` par les lignes de code suivantes :
244 |
245 | ```python
246 | # définissez async_mode sur 'threading', 'eventlet', 'gevent' ou 'gevent_uwsgi' sur
247 | # forcer un autre mode, le meilleur mode est sélectionné automatiquement parmi ce qui est
248 | # installée
249 | sync_mode = 'gevent';
250 |
251 | import os
252 |
253 | from django.http import HttpResponse
254 | import socketio
255 |
256 | basedir = os.path.dirname(os.path.realpath(__file__));
257 | sio = socketio.Server(async_mode=async_mode);
258 |
259 | # thread = None
260 | users = {};
261 |
262 | def index(request):
263 | """
264 | Programme qui permet de renvoiyer la page web `index`
265 | """
266 |
267 | # global thread;
268 |
269 | # if thread is None:
270 | # thread = sio.start_background_task(background_thread);
271 |
272 | return HttpResponse(open(os.path.join(basedir, 'static/index.html')));
273 |
274 |
275 | # def background_thread():
276 | # """ Exemple de programme d'execution de programme d'arriere plan """
277 |
278 | # count = 0;
279 |
280 | # while True:
281 | # sio.sleep(10);
282 | # count += 1;
283 | # sio.emit('my_response', {'data': 'Server generated event'}, namespace='/test');
284 |
285 | @sio.event
286 | def set_username(sid, message):
287 | """ Programme de modification du nom d'utilisateur """
288 | users[sid] = message['data'];
289 |
290 | # on notifit que le username a ete correctement notifie
291 | sio.emit('my_response', {'data': f"Username is set to {users[sid]} !"}, to=sid);
292 |
293 |
294 |
295 | @sio.event
296 | def my_event(sid, message):
297 | # Programme qui permet d'envoyer le message a moi meme
298 | sio.emit('my_response', {'data': message['data']}, room=sid);
299 |
300 |
301 |
302 | @sio.event
303 | def my_broadcast_event(sid, message):
304 | # Programme qui permet d'envoyer le message a tous le monde
305 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"});
306 |
307 |
308 |
309 | @sio.event
310 | def join(sid, message):
311 | """ Programme de creation et d'adesion de canale """
312 |
313 | # on cree le canale et on se join a ce canal
314 | sio.enter_room(sid, message['room']);
315 |
316 | # sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, room=sid);
317 |
318 | # on emet a tous ceux qui sont dans le canal qu'on de
319 | # rejoindre le canal
320 | sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, to=message['room']);
321 |
322 |
323 | @sio.event
324 | def leave(sid, message):
325 | """ Programme de deconnection d'un canal """
326 |
327 | # on se deconnecte du canal
328 | sio.leave_room(sid, message['room']);
329 |
330 | # on informe tous ceux qui sont dans le canal, que celui-ci
331 | # a quitte le canal
332 | sio.emit('my_response', {'data': users[sid] + ' left room: ' + message['room']}, room=message['room']);
333 |
334 |
335 | @sio.event
336 | def close_room(sid, message):
337 | """ Programme de fermeture d'un canal """
338 |
339 | # on ferme le canal
340 | sio.close_room(message['room']);
341 | sio.emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.'}, room=message['room']);
342 |
343 |
344 | @sio.event
345 | def my_room_event(sid, message):
346 | """ Programme qui permet d'envoyer un message a tous les membres du canal """
347 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"}, room=message['room']);
348 |
349 |
350 | @sio.event
351 | def disconnect_request(sid):
352 | """ Programme qui declanche la deconnection de l'utilisateur """
353 | sio.disconnect(sid);
354 |
355 |
356 | @sio.event
357 | def connect(sid, environ):
358 | """ Programme de connexion
359 | Au cour de la connexion, on enregistre tous les utilisateurs
360 | connectes
361 | """
362 |
363 | print(f"{sid}\t connected");
364 |
365 | # on ajoute le nouveau a la liste
366 | users[sid] = None;
367 |
368 | # on lui notifie qu'il s'est bien connecte
369 | sio.emit('my_response', {'data': 'Connected', 'count': len(users)}, room=sid);
370 |
371 | # on notifie a tous le monde le nombre de personnes actuellement connectes
372 | sio.emit('my_response', {'data': f'{len(users)} connected now!', 'count': len(users)});
373 |
374 |
375 | @sio.event
376 | def disconnect(sid):
377 | """ Programme de deconnexion
378 | Lors de la deconnexion, on supprime l'utilisateur de la liste des
379 | connectes
380 | """
381 |
382 | print(f"{sid}\t {users[sid]} disconnected");
383 |
384 | # on notifie a tous le monde le nombre de personnes actuellement connectes
385 | sio.emit('my_response', {'data': f"{users[sid]} is disconnected", 'count': len(users)});
386 |
387 | # on le supprime de la liste
388 | del users[sid];
389 |
390 | # on notifie a tous le monde le nombre de personnes actuellement connectes
391 | sio.emit('my_response', {'data': f'{len(users)} connected', 'count': len(users)});
392 |
393 |
394 |
395 |
396 | ```
397 |
398 | ### Programme client
399 | En effet, il s'agit de mettre en place une interface WEB.
400 | Dans le dossier `django_socketio/socketio_app/`, créez un dossier nommé `static`, ensuite, dans ce dernier, créer un fichier nommé `index.html`. Dans ce fichier, insérez les lignes de code suivantes :
401 |
402 | ```html
403 |
404 |
405 |
406 | Django + SocketIO Test
407 |
408 |
409 |
461 |
462 |
463 | Django + SocketIO Test
464 | Send:
465 |
469 |
473 |
477 |
481 |
485 |
490 |
494 |
497 | Receive:
498 |
499 |
500 |
501 |
502 | ```
503 |
504 |
505 |
506 | ## Démarrage du serveur
507 | N'oublier pas de sauvegarder tous les fichiers sources. Il est temps de tester notre programme.
508 | On doit d'abord faire un migration dans une base de données avant de démarrer le serveur.
509 | Pour faire la migration, tappez la commande suivante :
510 |
511 | ```
512 | ./manage.py migrate
513 | ```
514 |
515 | On peut maintenant démarrer le serveur avec la commande suivante :
516 |
517 | ```
518 | ./manage.py runserver
519 | ```
520 |
521 | Si tout va bien, vous verrez le message suivant affichez dans votre terminal.
522 |
523 | ```
524 | Watching for file changes with StatReloader
525 | Performing system checks...
526 |
527 | System check identified no issues (0 silenced).
528 | August 30, 2021 - 01:55:05
529 | Django version 3.2.6, using settings 'django_socketio.settings'
530 | Starting development server at http://127.0.0.1:8000/
531 | Quit the server with CONTROL-C.
532 | ```
533 |
534 |
535 |
536 | ## Test
537 | Voici le lien pour accéder à l'interface web : [http://127.0.0.1:8000/](http://127.0.0.1:8000/).
538 | Pour que d'autre ordinateur puisse accéder à votre application, il faut qu'ils soient dans le même réseau que votre ordinateur. Ensuite, ils doivent utiliser votre adresse IP (souvent sous la forme `192.168.xxx.xxx`). Pour connaitre votre adresse IP :
539 |
540 | - sous linux :
541 |
542 | ```
543 | sudo ifconfig
544 | ```
545 |
546 | - sous windows :
547 |
548 | ```
549 | ipconfig
550 | ```
551 | Ensuite rendez-vous dans le fichier `django_socketio/settings.py` pour permettre l'accès au serveur via cet adresse IP. Si par exemple mon adresse IP est `192.168.100.31`, alors vous devez modifier la ligne de code suivante dans le fichier `django_socketio/settings.py`
552 |
553 | ```python
554 | # ...
555 |
556 | ALLOWED_HOSTS = ['192.168.100.31'];
557 |
558 | # La ligne ci-dessus permettra au autre ordinateur qui sont sur le même réseau que moi
559 | # de pouvoir accéder à mon serveur socket.io via le lien http://192.168.100.31:8000/
560 |
561 | # ...
562 | ```
563 |
564 |
565 |
566 |
567 | ## Système d'exploitation
568 |
569 | ```
570 | Kernel: 5.8.0-59-generic x86_64 bits: 64 compiler: N/A Desktop: Gnome 3.36.9
571 | Distro: Ubuntu 20.04.2 LTS (Focal Fossa)
572 | ```
573 |
574 |
575 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_socketio.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.4.1
2 | bidict==0.21.2
3 | Django==3.2.6
4 | dnspython==1.16.0
5 | enum-compat==0.0.3
6 | eventlet==0.30.0
7 | gevent==21.1.2
8 | gevent-websocket==0.10.1
9 | greenlet==0.4.17
10 | python-engineio==4.2.1
11 | python-socketio==5.4.0
12 | pytz==2021.1
13 | six==1.10.0
14 | sqlparse==0.4.1
15 | zope.event==4.5.0
16 | zope.interface==5.4.0
17 |
--------------------------------------------------------------------------------
/socketio_app/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mokira3d48/python-socket.io-django/c6495f692c7915c00163e3cb19c85d9a9a17bf3d/socketio_app/__init__.py
--------------------------------------------------------------------------------
/socketio_app/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/socketio_app/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class SocketioAppConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'socketio_app'
7 |
--------------------------------------------------------------------------------
/socketio_app/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mokira3d48/python-socket.io-django/c6495f692c7915c00163e3cb19c85d9a9a17bf3d/socketio_app/migrations/__init__.py
--------------------------------------------------------------------------------
/socketio_app/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/socketio_app/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Django + SocketIO Test
5 |
6 |
7 |
59 |
60 |
61 | Django + SocketIO Test
62 | Send:
63 |
67 |
71 |
75 |
79 |
83 |
88 |
92 |
95 | Receive:
96 |
97 |
98 |
--------------------------------------------------------------------------------
/socketio_app/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/socketio_app/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | from . import views
4 |
5 | urlpatterns = [
6 | url(r'', views.index, name='index'),
7 | ];
8 |
9 |
--------------------------------------------------------------------------------
/socketio_app/views.py:
--------------------------------------------------------------------------------
1 | # set async_mode to 'threading', 'eventlet', 'gevent' or 'gevent_uwsgi' to
2 | # force a mode else, the best mode is selected automatically from what's
3 | # installed
4 | async_mode = 'gevent';
5 |
6 | import os
7 |
8 | from django.http import HttpResponse
9 | import socketio
10 |
11 | basedir = os.path.dirname(os.path.realpath(__file__));
12 | sio = socketio.Server(async_mode=async_mode);
13 |
14 | # thread = None
15 | users = {};
16 |
17 | def index(request):
18 | """
19 | Programme qui permet de renvoiyer la page web `index`
20 | """
21 |
22 | # global thread;
23 |
24 | # if thread is None:
25 | # thread = sio.start_background_task(background_thread);
26 |
27 | return HttpResponse(open(os.path.join(basedir, 'static/index.html')));
28 |
29 |
30 | # def background_thread():
31 | # """ Exemple de programme d'execution de programme d'arriere plan """
32 |
33 | # count = 0;
34 |
35 | # while True:
36 | # sio.sleep(10);
37 | # count += 1;
38 | # sio.emit('my_response', {'data': 'Server generated event'}, namespace='/test');
39 |
40 | @sio.event
41 | def set_username(sid, message):
42 | """ Programme de modification du nom d'utilisateur """
43 | users[sid] = message['data'];
44 |
45 | # on notifit que le username a ete correctement notifie
46 | sio.emit('my_response', {'data': f"Username is set to {users[sid]} !"}, to=sid);
47 |
48 |
49 |
50 | @sio.event
51 | def my_event(sid, message):
52 | # Programme qui permet d'envoyer le message a moi meme
53 | sio.emit('my_response', {'data': message['data']}, room=sid);
54 |
55 |
56 |
57 | @sio.event
58 | def my_broadcast_event(sid, message):
59 | # Programme qui permet d'envoyer le message a tous le monde
60 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"});
61 |
62 |
63 |
64 | @sio.event
65 | def join(sid, message):
66 | """ Programme de creation et d'adesion de canale """
67 |
68 | # on cree le canale et on se join a ce canal
69 | sio.enter_room(sid, message['room']);
70 |
71 | # sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, room=sid);
72 |
73 | # on emet a tous ceux qui sont dans le canal qu'on de
74 | # rejoindre le canal
75 | sio.emit('my_response', {'data': 'Entered room: ' + message['room']}, to=message['room']);
76 |
77 |
78 | @sio.event
79 | def leave(sid, message):
80 | """ Programme de deconnection d'un canal """
81 |
82 | # on se deconnecte du canal
83 | sio.leave_room(sid, message['room']);
84 |
85 | # on informe tous ceux qui sont dans le canal, que celui-ci
86 | # a quitte le canal
87 | sio.emit('my_response', {'data': users[sid] + ' left room: ' + message['room']}, room=message['room']);
88 |
89 |
90 | @sio.event
91 | def close_room(sid, message):
92 | """ Programme de fermeture d'un canal """
93 |
94 | # on ferme le canal
95 | sio.close_room(message['room']);
96 | sio.emit('my_response', {'data': 'Room ' + message['room'] + ' is closing.'}, room=message['room']);
97 |
98 |
99 | @sio.event
100 | def my_room_event(sid, message):
101 | """ Programme qui permet d'envoyer un message a tous les membres du canal """
102 | sio.emit('my_response', {'data': f"[{users[sid]}] {message['data']}"}, room=message['room']);
103 |
104 |
105 | @sio.event
106 | def disconnect_request(sid):
107 | """ Programme qui declanche la deconnection de l'utilisateur """
108 | sio.disconnect(sid);
109 |
110 |
111 | @sio.event
112 | def connect(sid, environ):
113 | """ Programme de connexion
114 | Au cour de la connexion, on enregistre tous les utilisateurs
115 | connectes
116 | """
117 |
118 | print(f"{sid}\t connected");
119 |
120 | # on ajoute le nouveau a la liste
121 | users[sid] = None;
122 |
123 | # on lui notifie qu'il s'est bien connecte
124 | sio.emit('my_response', {'data': 'Connected', 'count': len(users)}, room=sid);
125 |
126 | # on notifie a tous le monde le nombre de personnes actuellement connectes
127 | sio.emit('my_response', {'data': f'{len(users)} connected now!', 'count': len(users)});
128 |
129 |
130 | @sio.event
131 | def disconnect(sid):
132 | """ Programme de deconnexion
133 | Lors de la deconnexion, on supprime l'utilisateur de la liste des
134 | connectes
135 | """
136 |
137 | print(f"{sid}\t {users[sid]} disconnected");
138 |
139 | # on notifie a tous le monde le nombre de personnes actuellement connectes
140 | sio.emit('my_response', {'data': f"{users[sid]} is disconnected", 'count': len(users)});
141 |
142 | # on le supprime de la liste
143 | del users[sid];
144 |
145 | # on notifie a tous le monde le nombre de personnes actuellement connectes
146 | sio.emit('my_response', {'data': f'{len(users)} connected', 'count': len(users)});
147 |
148 |
149 |
--------------------------------------------------------------------------------