Python Socket.io reference

Some links to get you started

Demo project

index.py

from flask import Flask
from flask import jsonify
from flask import sessions
from flask import request
from flask import send_file
from flask import render_template
from flask_socketio import SocketIO, emit
from datetime import datetime
from werkzeug.utils import secure_filename
import sqlite3
import os
import json

### Globals

app = Flask(__name__)
app.config['SECRET_KEY'] = 'booyeah!secret!'
socketio = SocketIO(app)

clients = []

### Define routes

@app.route('/')
def home():
    pass

@app.route('/chat')
def chat():
    return render_template('chat.html')

@socketio.on('connect')
def client_connect():
    print("Received connection from {0}".format(request.sid))
    clients.append(request.sid)

@socketio.on('disconnect')
def client_disconnect():
    clients.remove(request.sid)

@socketio.on('yo')
def receive_message(message):
    # Note: because I sent a JSON object from the client, this has automatically done json.loads() on it and given me an object
    print(type(message))
    print("Message from {0} says: {1}".format(message["nickname"], message["message"]))
    emit("oohyeah", message, broadcast=True)

if __name__ == "__main__":
    # app.run() is replaced by socketio.run()
    # app.run(host='0.0.0.0', port=8080)
    socketio.run(app,host='0.0.0.0', port=8080)

Notes:

The emit() function parameters:

  • event identifier (used by the client for their "on message" event handler)
  • dictionary based message (a json packet for sending to the client, ie: the sort created by json.loads())
  • optional named arguments, the most likely being:
    • broadcast=True/False ... send to all or only the originating client
    • room=roomID ... broadcast to a room
    • include_self=True/False ... send to originating client or everyone but

When a client connects, it triggers a connect event (reserved word). Recommend populating and de-populating a clients list based on connect/disconnect events as shown. Would allow you to message clients independently such as...

def send_random_messages():
    msg = {}
    for client in clients:
        msg["nickname"] = "The Server"
        msg["message"] = "Hello client "+client
        socketio.emit("oohyeah", msg, room=client)

Also be aware there is a difference between using emit() and socketio.emit() in the event handling function. The emit() is in the context of the received message so will know who the client was for sending just client based replies. The socketio.emit() does not know the client and will broadcast to all.

chat.html

<!DOCTYPE html>
<html lang="en">
<head><title>Socket.IO chat example</title></head>
<body>
  Your nickname: <input type="text" id="nickname"><br>
  Message:<br>
  <textarea type="text" id="message" rows="5" cols="50"></textarea>
  <input type="button" id="send" value="Send">
  <hr>
  <h1>Messages received:</h1>
  <p id="messages"></p>
</body>
<script src="/static/js/socket.io.js"></script>
<script language="JavaScript">
"use strict";

function app() {
  var socket = io(); // Make connection to server

  function send() {
    var nick = document.getElementById("nickname").value;
    var msg = document.getElementById("message").value;
    var packet = {
      "message" : msg,
      "nickname" : nick
    };
    socket.emit("yo", packet);
  }

  function receiveMessage(data) {
    console.log("Recieved message ",data);
    var s = "<b>["+ data.nickname +"]</b> "+data.message + "<br>\n";
    document.getElementById("messages").innerHTML += s;
  };

  document.getElementById("send").addEventListener("click", send);
  socket.on("oohyeah", receiveMessage); // Set socket event listener
}
window.onload=app; // Execute app once page fully loaded
</script>
</html>