├── README.md
├── public
├── index.html
└── index.js
├── .gitignore
├── requirements.txt
├── LICENSE
├── async_client.py
├── client.py
├── app.py
└── async_app.py
/README.md:
--------------------------------------------------------------------------------
1 | Quick Socket.IO Tutorial
2 | ========================
3 |
4 | This repository contains the code from my video series "Quick Socket.IO
5 | Tutorial".
6 |
7 | Watch it on YouTube: https://www.youtube.com/watch?v=H1eLJMC5oTg&list=PLCuWRxjbgFnPZTBMYbz9UNGvTLNggRMjb
8 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Socket.IO Demo
5 |
6 |
7 | Socket.IO Demo
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 |
3 | # C extensions
4 | *.so
5 |
6 | # Packages
7 | *.egg
8 | *.egg-info
9 | dist
10 | build
11 | eggs
12 | parts
13 | var
14 | sdist
15 | develop-eggs
16 | .installed.cfg
17 | lib
18 | lib64
19 | __pycache__
20 |
21 | # Installer logs
22 | pip-log.txt
23 |
24 | # Unit test / coverage reports
25 | .coverage
26 | .tox
27 | nosetests.xml
28 |
29 | # Translations
30 | *.mo
31 |
32 | # Mr Developer
33 | .mr.developer.cfg
34 | .project
35 | .pydevproject
36 |
37 | docs/_build
38 | venv*
39 | .eggs
40 | .ropeproject
41 | .idea
42 | .vscode
43 | tags
44 | htmlcov
45 | *.swp
46 |
47 | node_modules
48 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohttp==3.7.3
2 | async-timeout==3.0.1
3 | attrs==20.3.0
4 | bidict==0.21.2
5 | certifi==2020.12.5
6 | chardet==3.0.4
7 | click==7.1.2
8 | dnspython==1.16.0
9 | eventlet==0.30.0
10 | greenlet==0.4.17
11 | gunicorn==20.0.4
12 | h11==0.11.0
13 | httptools==0.1.1
14 | idna==2.10
15 | multidict==5.1.0
16 | python-dotenv==0.15.0
17 | python-engineio==4.0.0
18 | python-socketio==5.0.4
19 | PyYAML==5.3.1
20 | requests==2.25.1
21 | six==1.15.0
22 | typing-extensions==3.7.4.3
23 | urllib3==1.26.2
24 | uvicorn==0.13.2
25 | uvloop==0.14.0
26 | watchgod==0.6
27 | websocket-client==0.57.0
28 | websockets==8.1
29 | yarl==1.6.3
30 |
--------------------------------------------------------------------------------
/public/index.js:
--------------------------------------------------------------------------------
1 | const sio = io({
2 | transportOptions: {
3 | polling: {
4 | extraHeaders: {
5 | 'X-Username': window.location.hash.substring(1)
6 | }
7 | }
8 | }
9 | });
10 |
11 | sio.on('connect', () => {
12 | console.log('connected');
13 | sio.emit('sum', {numbers: [1, 2]}, (result) => {
14 | console.log(result);
15 | });
16 | });
17 |
18 | sio.on('connect_error', (e) => {
19 | console.log(e.message);
20 | });
21 |
22 | sio.on('disconnect', () => {
23 | console.log('disconnected');
24 | });
25 |
26 | sio.on('mult', (data, cb) => {
27 | const result = data.numbers[0] * data.numbers[1];
28 | cb(result);
29 | });
30 |
31 | sio.on('client_count', (count) => {
32 | console.log('There are ' + count + ' connected clients.');
33 | });
34 |
35 | sio.on('room_count', (count) => {
36 | console.log('There are ' + count + ' clients in my room.');
37 | });
38 |
39 | sio.on('user_joined', (username) => {
40 | console.log('User ' + username + ' has joined.');
41 | });
42 |
43 | sio.on('user_left', (username) => {
44 | console.log('User ' + username + ' has left.');
45 | });
46 |
--------------------------------------------------------------------------------
/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.
21 |
--------------------------------------------------------------------------------
/async_client.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import socketio
3 |
4 | sio = socketio.AsyncClient()
5 |
6 |
7 | @sio.event
8 | async def connect():
9 | print('connected')
10 | result = await sio.call('sum', {'numbers': [1, 2]})
11 | print(result)
12 |
13 |
14 | @sio.event
15 | async def connect_error(e):
16 | print(e)
17 |
18 |
19 | @sio.event
20 | async def disconnect():
21 | print('disconnected')
22 |
23 |
24 | @sio.event
25 | async def mult(data):
26 | return data['numbers'][0] * data['numbers'][1]
27 |
28 |
29 | @sio.event
30 | async def client_count(count):
31 | print('There are', count, 'connected clients.')
32 |
33 |
34 | @sio.event
35 | async def room_count(count):
36 | print('There are', count, 'clients in my room.')
37 |
38 |
39 | @sio.event
40 | async def user_joined(username):
41 | print('User', username, 'has joined.')
42 |
43 |
44 | @sio.event
45 | async def user_left(username):
46 | print('User', username, 'has left.')
47 |
48 |
49 | async def main():
50 | await sio.connect('http://localhost:8000',
51 | headers={'X-Username': 'miguel'})
52 | await sio.wait()
53 |
54 |
55 | asyncio.run(main())
56 |
--------------------------------------------------------------------------------
/client.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import sys
3 | import socketio
4 |
5 | sio = socketio.Client()
6 |
7 |
8 | @sio.event
9 | def connect():
10 | print('connected')
11 | result = sio.call('sum', {'numbers': [1, 2]})
12 | print(result)
13 |
14 |
15 | @sio.event
16 | def connect_error(e):
17 | print(e)
18 |
19 |
20 | @sio.event
21 | def disconnect():
22 | print('disconnected')
23 |
24 |
25 | @sio.event
26 | def mult(data):
27 | return data['numbers'][0] * data['numbers'][1]
28 |
29 |
30 | @sio.event
31 | def client_count(count):
32 | print('There are', count, 'connected clients.')
33 |
34 |
35 | @sio.event
36 | def room_count(count):
37 | print('There are', count, 'clients in my room.')
38 |
39 |
40 | @sio.event
41 | def user_joined(username):
42 | print('User', username, 'has joined.')
43 |
44 |
45 | @sio.event
46 | def user_left(username):
47 | print('User', username, 'has left.')
48 |
49 |
50 | def main(username):
51 | sio.connect('http://localhost:8000',
52 | headers={'X-Username': username})
53 | sio.wait()
54 |
55 |
56 | if __name__ == '__main__':
57 | main(sys.argv[1] if len(sys.argv) > 1 else None)
58 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import random
2 | import socketio
3 |
4 | sio = socketio.Server()
5 | app = socketio.WSGIApp(sio, static_files={
6 | '/': './public/'
7 | })
8 | client_count = 0
9 | a_count = 0
10 | b_count = 0
11 |
12 |
13 | def task(sid):
14 | sio.sleep(5)
15 | result = sio.call('mult', {'numbers': [3, 4]}, to=sid)
16 | print(result)
17 |
18 |
19 | @sio.event
20 | def connect(sid, environ):
21 | global client_count
22 | global a_count
23 | global b_count
24 |
25 | username = environ.get('HTTP_X_USERNAME')
26 | print('username:', username)
27 | if not username:
28 | return False
29 |
30 | with sio.session(sid) as session:
31 | session['username'] = username
32 | sio.emit('user_joined', username)
33 |
34 | client_count += 1
35 | print(sid, 'connected')
36 | sio.start_background_task(task, sid)
37 | sio.emit('client_count', client_count)
38 | if random.random() > 0.5:
39 | sio.enter_room(sid, 'a')
40 | a_count += 1
41 | sio.emit('room_count', a_count, to='a')
42 | else:
43 | sio.enter_room(sid, 'b')
44 | b_count += 1
45 | sio.emit('room_count', b_count, to='b')
46 |
47 |
48 | @sio.event
49 | def disconnect(sid):
50 | global client_count
51 | global a_count
52 | global b_count
53 | client_count -= 1
54 | print(sid, 'disconnected')
55 | sio.emit('client_count', client_count)
56 | if 'a' in sio.rooms(sid):
57 | a_count -= 1
58 | sio.emit('room_count', a_count, to='a')
59 | else:
60 | b_count -= 1
61 | sio.emit('room_count', b_count, to='b')
62 |
63 | with sio.session(sid) as session:
64 | sio.emit('user_left', session['username'])
65 |
66 |
67 | @sio.event
68 | def sum(sid, data):
69 | result = data['numbers'][0] + data['numbers'][1]
70 | return {'result': result}
71 |
--------------------------------------------------------------------------------
/async_app.py:
--------------------------------------------------------------------------------
1 | import random
2 | import socketio
3 |
4 | sio = socketio.AsyncServer(async_mode='asgi')
5 | app = socketio.ASGIApp(sio, static_files={
6 | '/': './public/'
7 | })
8 | client_count = 0
9 | a_count = 0
10 | b_count = 0
11 |
12 |
13 | async def task(sid):
14 | await sio.sleep(5)
15 | result = await sio.call('mult', {'numbers': [3, 4]}, to=sid)
16 | print(result)
17 |
18 |
19 | @sio.event
20 | async def connect(sid, environ):
21 | global client_count
22 | global a_count
23 | global b_count
24 |
25 | username = environ.get('HTTP_X_USERNAME')
26 | print('username:', username)
27 | if not username:
28 | return False
29 |
30 | async with sio.session(sid) as session:
31 | session['username'] = username
32 | await sio.emit('user_joined', username)
33 |
34 | client_count += 1
35 | print(sid, 'connected')
36 | sio.start_background_task(task, sid)
37 | await sio.emit('client_count', client_count)
38 | if random.random() > 0.5:
39 | sio.enter_room(sid, 'a')
40 | a_count += 1
41 | await sio.emit('room_count', a_count, to='a')
42 | else:
43 | sio.enter_room(sid, 'b')
44 | b_count += 1
45 | await sio.emit('room_count', b_count, to='b')
46 |
47 |
48 | @sio.event
49 | async def disconnect(sid):
50 | global client_count
51 | global a_count
52 | global b_count
53 | client_count -= 1
54 | print(sid, 'disconnected')
55 | await sio.emit('client_count', client_count)
56 | if 'a' in sio.rooms(sid):
57 | a_count -= 1
58 | await sio.emit('room_count', a_count, to='a')
59 | else:
60 | b_count -= 1
61 | await sio.emit('room_count', b_count, to='b')
62 |
63 | async with sio.session(sid) as session:
64 | await sio.emit('user_left', session['username'])
65 |
66 |
67 | @sio.event
68 | async def sum(sid, data):
69 | result = data['numbers'][0] + data['numbers'][1]
70 | return {'result': result}
71 |
--------------------------------------------------------------------------------