Socket io

Socket.IO is a JavaScript library for real-time web applications. It enables bi-directional, event-based communication between clients (typically browsers or native apps) and servers.

#Installation / Setup

#Installation / Setup

JavaScript (Node.js)

npm install socket.io socket.io-client

Python

pip install python-socketio eventlet
# or
pip install python-socketio aiohttp

Java

implementation 'io.socket:socket.io-client:2.0.1'

#Installation / Setup

Swift (iOS)

pod 'Socket.IO-Client-Swift', '~> 16.0.1'

C# (.NET)

Install-Package SocketIoClientDotNet

React Native

npm install socket.io-client

#Installation / Setup

Go

go get github.com/googollee/go-socket.io

Rust


cargo add socketio-client


#Connecting / Setup

#JavaScript (Browser Client then Node.js Server)

Client

import { io } from 'socket.io-client';
const socket = io('http://localhost:3000');

Server

const io = require('socket.io')(3000, {
  cors: { origin: '*' }
});
io.on('connection', (socket) => {
  console.log('Client connected:', socket.id);
});

#Python (Client then Server)

Client

import socketio
sio = socketio.Client()
sio.connect('http://localhost:3000')

Server

import socketio, eventlet, flask

app = flask.Flask(__name__)
sio = socketio.Server(cors_allowed_origins='*')
app = socketio.WSGIApp(sio, app)

@sio.event
def connect(sid, environ):
    print('Client connected:', sid)

if __name__ == '__main__':
    eventlet.wsgi.server(eventlet.listen(('', 3000)), app)

#Java (Client then Server)

Client

IO.Options opts = new IO.Options();
Socket socket = IO.socket("http://localhost:3000", opts);
socket.connect();

Server

import io.socket.engineio.server.EngineIoServer;
import io.socket.server.SocketIoServer;

EngineIoServer engineIo = new EngineIoServer();
SocketIoServer io = new SocketIoServer(engineIo);
io.listen(3000);

io.on("connection", args -> {
    var client = args[0];
    System.out.println("Client connected: " + client.id());
});

#Swift (iOS Client then Server)

Client

let manager = SocketManager(
  socketURL: URL(string: "http://localhost:3000")!,
  config: [.log(true), .compress]
)
let socket = manager.defaultSocket
socket.connect()

Server Server setups in Swift are uncommon; usually Node.js or Python is used.

#C# (.NET Client then Server)

Client

var socket = IO.Socket("http://localhost:3000");
socket.Connect();

Server

using Fleck;
var server = new WebSocketServer("ws://0.0.0.0:3000");
server.Start(socket =>
{
    socket.OnOpen = () => Console.WriteLine("Client connected");
});

#React Native (Client)

Client

import io from 'socket.io-client';
const socket = io('http://localhost:3000');

(Server side same as JavaScript above.)

#Go (Client then Server)

Client

import "github.com/googollee/go-socket.io-client"
socket, err := gosocketio.Dial(
    gosocketio.GetUrl("localhost", 3000, false),
    transport.GetDefaultWebsocketTransport(),
)

Server

import (
    "github.com/googollee/go-socket.io"
    "net/http"
)

server, _ := socketio.NewServer(nil)
server.OnConnect("/", func(s socketio.Conn) error {
    fmt.Println("Client connected:", s.ID())
    return nil
})
http.Handle("/socket.io/", server)
go http.ListenAndServe(":3000", nil)

#Rust (Client then Server)

Client

use socketio_client::ClientBuilder;

async fn run() -> Result<(), Box<dyn std::error::Error>> {
    let socket = ClientBuilder::new("http://localhost:3000")
        .transport("websocket")
        .connect()
        .await?;
    Ok(())
}

Server Rust server support is experimental; commonly use Node.js/Python servers.


#Emitting & Listening to Events

#JavaScript (Client then Server)

Client

socket.emit('msg', 'Hi');
socket.on('reply', (data) => console.log('Reply:', data));

Server

io.on('connection', (socket) => {
  socket.on('msg', (msg) => {
    console.log('Received:', msg);
    socket.emit('reply', 'Hello from server');
  });
});

#Python (Client then Server)

Client

sio.emit('msg', 'Hi')

@sio.on('reply')
def on_reply(data):
    print('Reply:', data)

Server

@sio.event
def msg(sid, data):
    print('Received:', data)
    sio.emit('reply', 'Hello from server', to=sid)

#Java (Client then Server)

Client

socket.emit("msg", "Hi");
socket.on("reply", args -> System.out.println("Reply: " + args[0]));

Server

io.on("connection", args -> {
    var client = args[0];
    client.on("msg", msgArgs -> {
        System.out.println("Received: " + msgArgs[0]);
        client.emit("reply", "Hello from server");
    });
});

#Swift (Client then Server)

Client

socket.emit("msg", "Hi")
socket.on("reply") { data, _ in
  print("Reply:", data[0])
}

Server Server side in Swift is rare; use Node.js/Python.

#C# (Client then Server)

Client

socket.Emit("msg", "Hi");
socket.On("reply", data => Console.WriteLine("Reply: " + data));

Server

socket.OnMessage = message =>
{
    Console.WriteLine("Received: " + message);
    socket.Send("reply", "Hello from server");
};

#Go (Client then Server)

Client

socket.Emit("msg", "Hi")
socket.On("reply", func(msg string) {
    fmt.Println("Reply:", msg)
})

Server

server.OnEvent("/", "msg", func(s socketio.Conn, msg string) {
    fmt.Println("Received:", msg)
    s.Emit("reply", "Hello from server")
})

#Rust (Client then Server)

Client

socket.emit("msg", Payload::String("Hi"));
socket.on("reply", |payload| println!("Reply: {:?}", payload));

Server Experimental; typically use Node.js/Python.


#Broadcasting & Rooms

#Client (All Languages)

  • Join a room:

    // JavaScript/Python/C#/etc.
    socket.emit('join', 'room1');
    socket.on('msg', (data) => console.log('Room message:', data));
    

#Server (All Languages)

  • Node.js

    io.on('connection', (socket) => {
      socket.on('join', (room) => {
        socket.join(room);
        io.to(room).emit('msg', 'Hello Room');
      });
    });
    
  • Python

    @sio.event
    def join(sid, room):
        sio.enter_room(sid, room)
        sio.emit('msg', 'Hello Room', room=room)
    
  • Go

    server.OnEvent("/", "join", func(s socketio.Conn, room string) {
        s.Join(room)
        server.BroadcastToRoom("/", room, "msg", "Welcome")
    })
    

#Disconnects & Errors

#Client (All Languages)

socket.on('disconnect', (reason) => console.log('Disconnected:', reason));
socket.on('connect_error', (err) => console.error('Connection error:', err));
@sio.event
def disconnect():
    print('Disconnected')

@sio.event
def connect_error(data):
    print('Connection error:', data)
// Go client library varies; similar patterns apply.

#Server (All Languages)

io.on('connection', (socket) => {
  socket.on('disconnect', (reason) =>
    console.log('Client disconnected:', reason)
  );
});
server.OnDisconnect("/", func(s socketio.Conn, reason string) {
    fmt.Println("Client disconnected:", reason)
})

#Namespaces

#Client (All Languages)

const adminSocket = io('/admin');
sio.connect('http://localhost:3000/admin', namespaces=['/admin'])

#Server (All Languages)

io.of('/admin').on('connection', (socket) => {
  console.log('Admin connected:', socket.id);
});
server.Of("/admin").OnConnect(func(s socketio.Conn) {
  fmt.Println("Admin connected:", s.ID())
})

#Authentication (Basic Token)

#Client (All Languages)

const socket = io('http://localhost:3000', {
  auth: { token: 'abc' }
});
sio.connect('http://localhost:3000', auth={'token': 'abc'})

#Server (All Languages)

io.use((socket, next) => {
  const token = socket.handshake.auth.token;
  token === 'abc' ? next() : next(new Error('Auth error'));
});

#Tips for Debugging & Logging

#Client

  • Log events:

    socket.onAny((event, ...args) => console.log(event, args));
    
  • Inspect network in browser devtools.

#Server

  • JavaScript

    DEBUG=socket.io* node server.js
    
  • Python

    import logging
    logging.getLogger('socketio').setLevel(logging.DEBUG)
    
  • Go Print handler errors and use middleware for structured logs.


#Advanced Features

#Middleware

Client (Rarely needed)

Server

io.use((socket, next) => {
  console.log('Middleware:', socket.id);
  next();
});
server.Use(func(s socketio.Conn, next func()) {
  fmt.Println("Middleware triggered:", s.ID())
  next()
})

#Binary Streaming

Client

fetch('/file')
  .then((res) => res.arrayBuffer())
  .then((buf) => socket.emit('file', buf));

Server

server.OnEvent("/", "file", func(s socketio.Conn, data []byte) {
    ioutil.WriteFile("upload", data, 0644)
})

#Best Practices