Socket.IO

repository·main·Indexed 13 days ago

https://github.com/socketio/socket.io

A library for real-time, bidirectional, and event-based communication between web clients and servers. It provides reliable connection handling in restrictive firewall environments or unstable networks, with support for horizontal scaling via Redis, @socket.io/cluster-engine, and various load balancers like Nginx, HAProxy, and Apache httpd.

Tokens
47.6K
Snippets
184
Records
256
Agent score
99%

What's inside Socket.IO

  1. Overview of Basic CRUD application implementations

    main

    The Basic CRUD application example provides different server-side implementations depending on your requirements for persistence and scaling:

    • Standard Implementation (server/): Uses TypeScript and an in-memory database. This is suitable for simple testing and does not support clustering.
    • Clustered Implementation (server-postgres-cluster/): Uses JavaScript, a Postgres database with the Postgres adapter, and supports clustering via the @socket.io/sticky module.
  2. Engine.IO Overview and Features

    main

    Engine.IO is the transport-based, cross-browser, and cross-device bi-directional communication layer used by Socket.IO. It is designed for maximum reliability and scalability.

    Key Features:

    • Maximum reliability: Maintains connections through proxies, load balancers, firewalls, and antivirus software.
    • Minimal client size: Achieved through lazy loading of transports and avoiding redundancy.
    • Scalable: Designed to be load balancer friendly.
    • Node.JS core style: Provides a low-level API without unnecessary abstraction sugar.
  3. Features of the Socket.IO Chat demo

    main

    The Socket.IO Chat demo demonstrates the following real-time capabilities:

    • User Management: Multiple users can join a chat room by entering a unique username when the website loads.
    • Messaging: Users can send and receive chat messages within the room.
    • Presence Notifications: The system automatically sends notifications to all connected users whenever a user joins or leaves the chatroom.
  4. What is the Socket.IO protocol and how does it work?

    main

    The Socket.IO protocol is a layer built on top of the Engine.IO protocol. While Engine.IO handles low-level transport (WebSocket and HTTP long-polling), the Socket.IO protocol provides high-level features including:

    • Multiplexing (Namespaces): Allows multiple logical communication channels over a single connection. For example, a client can connect to the default namespace / and a specific /admin namespace simultaneously.
    • Acknowledgements: A mechanism to confirm that a packet has been received by the other side.

    Example of Namespace multiplexing in JavaScript:

    // server-side
    const nsp = io.of("/admin");
    nsp.on("connect", socket => {});
    
    // client-side
    const socket1 = io(); // default namespace
    const socket2 = io("/admin");
    socket2.on("connect", () => {});

    Example of Acknowledgements in JavaScript:

    // on one side
    socket.emit("hello", 1, () => { console.log("received"); });
    // on the other side
    socket.on("hello", (a, cb) => { cb(); });
  5. What is the Socket.IO Protocol?

    main

    The Socket.IO protocol (v5) enables full-duplex, low-overhead communication between a client and a server. It is built on top of the Engine.IO protocol, which manages low-level transport mechanisms like WebSockets and HTTP long-polling.

    Socket.IO adds two primary high-level features to the transport layer:

    1. Multiplexing (Namespaces): Allows multiple logical communication channels (namespaces) to share a single underlying connection.
    2. Acknowledgements: Enables a request-response pattern where a sender can confirm that a receiver has processed a specific packet.
  6. Use custom parsers in Socket.IO

    main

    Since Socket.IO version 2.0.0, you can replace the default parser with a custom implementation to optimize for payload size or specific data types. This is useful when you need to reduce bandwidth (e.g., using Msgpack for numeric data) or when you have a strict schema (e.g., using Schemapack).

    Commonly used parsers include:

    • Default parser (socket.io-parser): Supports any serializable data structure, including Blob and File. Note that binary payloads are encoded as 2 packets.
    • Msgpack parser (socket.io-msgpack-parser): Greatly reduces the size of payloads containing mostly numeric values. Requires ArrayBuffer support in the browser (IE > 9).
    • JSON parser (socket.io-json-parser): An optimized JSON implementation, but it does not support binary payloads.
    • Schemapack parser: The most efficient in terms of both speed and size, but requires you to provide a schema for each packet.
  7. How Transport Upgrading Works

    main

    Connections always begin with polling (XHR or JSONP). The client tests for WebSocket support by sending a ping packet with the data probe. If the server responds with a pong packet containing probe, an upgrade packet is sent.

    To prevent message loss:

    1. The upgrade packet is only sent once all existing transport buffers are flushed and the transport is marked as _paused_.
    2. Upon receiving the upgrade packet, the server must switch to the new transport channel and flush any existing buffers to it.
  8. How Socket.IO works: Core Concepts

    main

    Socket.IO enables real-time bidirectional event-based communication. It is composed of a Node.js server and a client library (available for Browser, Node.js, Java, C++, Swift, Dart, Python, .NET, Rust, and PHP).

    Key Features

    • Reliability: Uses Engine.IO to establish long-polling connections and upgrade to WebSockets, helping bypass proxies and firewalls.
    • Auto-reconnection: Clients automatically attempt to reconnect indefinitely unless configured otherwise.
    • Disconnection Detection: Uses a heartbeat mechanism with pingInterval and pingTimeout parameters to detect unresponsive clients/servers.
    • Binary Support: Supports ArrayBuffer and Blob in the browser, and ArrayBuffer and Buffer in Node.js.
    • Multiplexing (Namespaces): Allows creating multiple Namespaces to separate concerns (e.g., per module) while sharing a single underlying connection.
    • Rooms: Within a Namespace, sockets can join or leave Rooms to facilitate broadcasting to specific groups of users.

    Important: Socket.IO is not a pure WebSocket implementation. It adds metadata (packet type, namespace, ack id) to every packet. Therefore, a standard WebSocket client cannot connect to a Socket.IO server, and a Socket.IO client cannot connect to a standard WebSocket server.

  9. Disconnection from a namespace

    main

    A side can end its connection to a specific namespace by sending a DISCONNECT packet. No response is required. If the client is connected to other namespaces, the underlying low-level connection may remain active.

    CLIENT                                                      SERVER
    
      │  ───────────────────────────────────────────────────────►  │
      │           { type: DISCONNECT, namespace: "/" }             │
  10. Understand Engine.IO Protocol v4 changes

    main

    The Engine.IO v4 protocol (included in Socket.IO v3.0.0 and above) introduced several critical changes to improve reliability and cross-language compatibility:

    • Reverse Ping/Pong: Ping packets are now sent by the server rather than the client. This addresses issues where client-side browser timers were unreliable and caused timeouts.
    • Binary Data Encoding:
      • For HTTP long-polling: All payloads containing binary data are encoded using base64. This allows the protocol to treat all payloads uniformly regardless of transport support.
      • For WebSocket: Binary data is sent in WebSocket frames without additional transformation.
    • Record Separator: The protocol now uses a record separator (\x1e) instead of character counting. This makes implementation easier in non-UTF-16 languages. Note: This assumes the record separator is not used within the data itself.
    • WebTransport Support: Added in version 4.1 (included in Socket.IO v4.6.0).
  11. Use Engine.IO without Socket.IO

    main

    While Socket.IO is the recommended framework for building realtime applications (as it provides multiplexing, reconnection support, etc.), you can use Engine.IO standalone.

    Think of Engine.IO as the essential engine (similar to how Connect relates to Express) that provides the raw realtime communication layer, whereas Socket.IO provides the higher-level application features.

  12. Understand the Socket.IO and Engine.IO protocol interaction

    main

    Socket.IO operates on top of the Engine.IO protocol. Engine.IO handles the low-level plumbing (transport like HTTP long-polling or WebSockets, heartbeats, and connection upgrades), while Socket.IO handles the high-level messaging (namespaces, events, and acknowledgements).

    When a session is established, the following sequence typically occurs:

    1. Engine.IO Handshake: An 'open' packet is sent via HTTP to establish the session, providing a sid (session ID) and available upgrades (e.g., websocket).
    2. Socket.IO Connection: Once the Engine.IO connection is open, a Socket.IO CONNECT packet is sent to connect to a namespace (the default or a specific one like /admin).
    3. Messaging: Events are sent using Engine.IO 'message' packets, which wrap Socket.IO 'EVENT' packets.
    4. Upgrades: The connection can be upgraded from polling to WebSocket using an Engine.IO 'upgrade' packet.
    /* Example of the packet layering: */
    // Engine.IO 'message' packet type (4) + Socket.IO 'EVENT' packet type (2)
    // Resulting in the prefix '42' in the raw wire format
    42["event_name", "payload"]