Socket.IO Blog https://socket.io/blog Socket.IO Blog Thu, 25 Jul 2024 00:00:00 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed en <![CDATA[npm package provenance]]> https://socket.io/blog/npm-package-provenance/ https://socket.io/blog/npm-package-provenance/ Thu, 25 Jul 2024 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We are happy to announce that Socket.IO packages will now be published with a provenance statement.

tip

Package provenance is a npm feature which was introduced last year to increase trust in the npm supply chain.

The idea is that the package is published and signed from a trusted CI/CD platform (such as GitHub Actions), so the code that ends up in the registry cannot be tampered with.

More info: https://github.blog/security/supply-chain-security/introducing-npm-package-provenance/

Starting today, new Socket.IO versions will be published directly from GitHub Actions and no longer from a maintainer machine.

The publication workflow can be found here: publish.yml

Notes

There are a few notable differences from the reference workflow:

Workflow trigger

The workflow is triggered when pushing a tag to GitHub:

on:
push:
tags:
- '**@*'

The expected format is <package>@<version>, for example:

The <package> part is then used to select the right workspace (since we are using a monorepo):

jobs:
publish:
steps:
# [...]

- name: Publish package
run: npm publish --workspace=${GITHUB_REF_NAME%@*} --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Reference: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions

Compilation step

A TypeScript compilation step is necessary, since some packages depend on the types of other packages:

jobs:
publish:
steps:
# [...]

- name: Compile each package
run: npm run compile --workspaces --if-present

- name: Publish package
# [...]

First verified version

The latest version of the engine.io-parser package has been released this way.

On the npmjs.com website, you can find:

  • the details of the build, at the bottom of the page:

Provenance details on www.npmjs.com

  • a checked badge, in the "Versions" tab

Provenance badge on www.npmjs.com

You can also verify the attestations of your dependencies:

$ npm i socket.io

added 22 packages, and audited 23 packages in 853ms

found 0 vulnerabilities

$ npm audit signatures

audited 22 packages in 1s

22 packages have verified registry signatures

1 package has a verified attestation # <-- it's a good start!

Conclusion

This is a big step forward in increasing trust in the JS ecosystem, congratulations to the npm team!

Some big names have already joined the club:

That's all folks, thanks for reading!

]]>
<![CDATA[Socket.IO monorepo]]> https://socket.io/blog/monorepo/ https://socket.io/blog/monorepo/ Fri, 12 Jul 2024 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We are happy to announce that the Socket.IO codebase has been merged into a monorepo.

note

A monorepo is a single repository containing multiple distinct projects, with well-defined relationships.

More info here

Modular architecture

As part of the work towards v1.0 ten years ago (!), the Socket.IO codebase was split into several packages, each with its own responsibility:

Diagram of the package inter-dependencies

At the time, tools like lerna or pnpm workspaces that make it easier to develop and publish multiple JavaScript packages from the same repository did not exist yet, so the codebase was split into multiple GitHub repositories:

However, this structure has several downsides:

  • it's harder for newcomers to dig into the codebase and understand what's going on under the hood
  • a change that affects multiple repositories is more difficult to test
  • mundane tasks like configuring CI or updating development dependencies must be replicated across all repositories

That's why we have made the decision to merge all repositories into a single one. The source codes for the different packages are now located in the packages/ directory:

packages/
├── engine.io
├── engine.io-client
├── engine.io-parser
├── socket.io
├── socket.io-adapter
├── socket.io-client
└── socket.io-parser

Workspaces

To manage the packages, we use npm workspaces which were introduced in npm v7 (bundled with Node.js v15). The package.json file at the root of the repository lists all packages and their development dependencies:

package.json
{
"private": true,
"workspaces": [
"packages/engine.io-parser",
"packages/engine.io",
"packages/engine.io-client",
"packages/socket.io-adapter",
"packages/socket.io-parser",
"packages/socket.io-client",
"packages/socket.io"
],
"devDependencies": {
// [...]
}
}

After cloning the repository, running npm install will fetch all necessary dependencies and create the links between the packages:

$ npm ls
socket.io@ /git/socket.io
└─┬ [email protected] -> ./packages/socket.io
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] -> ./packages/engine.io
├─┬ [email protected] -> ./packages/socket.io-adapter
│ ├── [email protected] deduped
│ └── [email protected] overridden
└─┬ [email protected] -> ./packages/socket.io-parser
├── @socket.io/[email protected] -> ./packages/socket.io-component-emitter
└── [email protected] deduped

And finally, running npm test --workspaces (or npm test -ws) will run the tests on all workspaces, ensuring that any change is properly tested over the whole codebase.

tip

Our contributing guide has been updated accordingly.

Git history

Obviously, losing 10 years of git history from the other repositories was not an option. The repositories have thus been merged with the --allow-unrelated-histories option, in order to include their history in the monorepo:

Schema of the preserved git history

Reference: https://git-scm.com/docs/git-merge#Documentation/git-merge.txt---allow-unrelated-histories

GitHub issues

Similarly, it was not conceivable to lose the list of open GitHub issues across all repositories, since it is our most valuable source of user feedback, so they have been moved to the main repository: https://github.com/socketio/socket.io/issues

Hopefully, this change should make it easier for anyone to contribute to the project in the future.

That's all folks, thanks for reading!

]]>
<![CDATA[Three new adapters]]> https://socket.io/blog/three-new-adapters/ https://socket.io/blog/three-new-adapters/ Fri, 29 Mar 2024 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

I'm happy to announce that we provide 3 new official adapters:

Any feedback is welcome!

]]>
<![CDATA[Chat platform]]> https://socket.io/blog/chat-platform/ https://socket.io/blog/chat-platform/ Fri, 12 Jan 2024 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

A new sample project is available: the Chat platform.

The source code can be found here.

for newcomers

Socket.IO is a library that enables low-latency, bidirectional and event-based communication between a client and a server.

To achieve this, it automatically selects the best available low-level transport between WebTransport, WebSocket and HTTP long-polling, based on the capabilities of the client platform and the network.

Goal

The goal of this project is to provide a full-blown project based on Socket.IO with:

  • authentication/user registration
  • public and private messaging
  • proper reconnection management
  • presence management

The source code is provided with a permissive MIT license, so that you can use it/extend it to your will.

How to use

Check out the code here and follow the instructions in the README.

Features

Channel-based messages

Screenshot of a public channel

Private messages

Screenshot of a private channel

Tools

Server

The server is written in plain JavaScript, with the express, express-session and passport packages. The database is PostgreSQL.

Client

The client is a Vue.js single-page application, with the vue-router and pinia packages. It uses Bootstrap v5 for the styles.

Roadmap

  • React client (link)
  • MongoDB server (link)

Any additional suggestion is welcome!

]]>
<![CDATA[Socket.IO on Azure]]> https://socket.io/blog/socket-io-on-azure-preview/ https://socket.io/blog/socket-io-on-azure-preview/ Wed, 23 Aug 2023 00:00:00 GMT <![CDATA[- Overview of Socket.IO support on Azure]]> <![CDATA[

Hello developers,

Since we put up an invitation to participate in a user study, we collected hundreds of responses and had the chance to speak in depth with several Socket.IO users. Thank you for your interest in the user study and helping us understand your experience.

In this post, I am going to share with you some notable learnings from the study. It’s our hope that such sharing can shed light on how we can build a stronger community as Socket.IO users, contributors, and cloud providers.

Socket.IO is used in a wide range of app scenarios

We were pleasantly surprised by the variety of applications built using Socket.IO. Although a fair number of users reported building chat apps using Socket.IO, many shared that they use Socket.IO for identity management to limit the number of active browser tabs, for robotics to control the movement of mobile robots, for multi-player mobile games and for collaborative apps where users can track work items in real-time.

Overwhelmingly, users enjoy the “intuitive APIs”

Users seem to have exhausted the synonyms for “intuitive” in their responses. Once users have gone over the initial learning curve, it doesn’t take long before they can get productive with Socket.IO’s APIs, which are described as “simple”, “easy” and “plain”. Plains APIs are definitely a praise in this case.

Some users seem to have doubts about Socket.IO’s viability for large projects

Users new to Socket.IO seem to have the impression that Socket.IO is for small-scale and toy projects and it would be necessary to find alternatives when an app needs to scale. I am happy to report that impression doesn’t reflect the reality; a few Socket.IO users shared that their apps handled 10s of thousand concurrent connections well, powered by running multiple Socket.IO instances behind a load balancer.

Scaling out a Socket.IO is where developers report the most pain

Scaling out a Socket.IO app requires a multi-server setup. Essentially, client connections are spread across several Socket.IO server instances. To emit an event to clients connected with different server instances, there needs to be a component to coordinate the message passing. While simple in broad-stroke description, implementation is not particularly straight-forward or familiar to most users. Deploying and maintaining a separate adapter component add additional complexity to the task.

This is an area where we studied the most and thought we could bring the most value to developers. I am happy to share with you that with the input from the open-source community, we brought support for Socket.IO on Azure. With this support, Azure hosts and manages client connections; in other words, developers don’t need an “adapter” component.

What’s more important is that server and client apps continue using the same and familiar Socket.IO APIs. With only a few lines of code, you can get any socket.io apps running locally to Azure. You can learn more about the support and try it out for free by following the links below.

]]>
<![CDATA[Redis Streams adapter]]> https://socket.io/blog/socket-io-redis-streams-adapter/ https://socket.io/blog/socket-io-redis-streams-adapter/ Fri, 07 Apr 2023 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

There is a new official adapter for Socket.IO: the Redis Streams adapter.

note

An Adapter is a server-side component which is responsible for forwarding packets within a cluster of Socket.IO servers.

More information here.

The adapter will use a Redis stream to forward packets between the Socket.IO servers.

The main difference with the existing Redis adapter (which use the Redis Pub/Sub mechanism) is that this adapter will properly handle any temporary disconnection to the Redis server and resume the stream without losing any packets.

See also:

If you have any feedback, feel free to open an issue in the repository.

]]>
<![CDATA[Socket.IO server for Deno]]> https://socket.io/blog/socket-io-deno/ https://socket.io/blog/socket-io-deno/ Tue, 13 Sep 2022 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

I'm happy to announce that Socket.IO is now compatible with Deno, which is a runtime for JavaScript and TypeScript written in Rust.

Usage:

import { serve } from "https://deno.land/[email protected]/http/server.ts";
import { Server } from "https://deno.land/x/[email protected]/mod.ts";

const io = new Server();

io.on("connection", (socket) => {
console.log(`socket ${socket.id} connected`);

socket.emit("hello", "world");

socket.on("disconnect", (reason) => {
console.log(`socket ${socket.id} disconnected due to ${reason}`);
});
});

await serve(io.handler(), {
port: 3000,
});

And then run with:

$ deno run --allow-net index.ts

The API is very similar to the one exposed by the Node.js implementation.

Next steps:

  • client implementation
  • compatibility with the Node.js ecosystem (msgpack parser, adapters, admin UI, ...)

Feedback is welcome!

]]>
<![CDATA[Socket.IO 4.5.0]]> https://socket.io/blog/socket-io-4-5-0/ https://socket.io/blog/socket-io-4-5-0/ Sat, 23 Apr 2022 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We have just published a new minor version of Socket.IO: 4.5.0

Here are the new features in this release:

Catch-all listeners for outgoing packets

This is similar to onAny(), but for outgoing packets.

Syntax:

socket.onAnyOutgoing((event, ...args) => {
console.log(event);
});

This feature can be used on both sides, and will also work when broadcasting events:

io.on("connection", (socket) => {
socket.onAnyOutgoing((event, ...args) => {
console.log(event); // prints "some event"
});

io.emit("some event");
});

Multiple acknowledgements when broadcasting

You can now broadcast an event to multiple clients and expect an acknowledgement:

io.timeout(10000).emit("some-event", (err, responses) => {
if (err) {
// some clients did not acknowledge the event in the given delay
} else {
console.log(responses); // one response per client
}
});

Limit the number of packets sent in HTTP long-polling mode

The server will now include the value of the maxHttpBufferSize in the handshake, so the clients will now be able to decide how many packets they have to send to stay under this value.

Here is what the handshake will now look like:

0{"sid":"lv_VI97HAXpY6yYWAAAC","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000,"maxPayload":1000000}

More information here.

Disconnection details

The "disconnect" event on the client side will now include additional details to help debugging if anything has gone wrong.

Example when sticky session is not enabled:

socket.on("disconnect", (reason, details) => {
console.log(details.context.status); // 400
console.log(details.context.responseText); // '{"code":1,"message":"Session ID unknown"}'
});

This release also includes some bug fixes, please see the complete diff below.

Size of the bundles:

minmin+gzip
socket.io.min.js42.6 KB (+ 2.2 KB ⬆️)13.6 KB (+ 0.5 KB ⬆️)
socket.io.msgpack.min.js47.7 KB (+ 2.1 KB ⬆️)14.6 KB (+ 0.4 KB ⬆️)
socket.io.esm.min.js34.5 KB (+ 1.4 KB ⬆️)11.5 KB (+ 0.2 KB ⬆️)

That's all for this release, thanks for reading!

]]>
<![CDATA[Socket.IO 4.4.0]]> https://socket.io/blog/socket-io-4-4-0/ https://socket.io/blog/socket-io-4-4-0/ Thu, 18 Nov 2021 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We have just published a new minor version of Socket.IO: 4.4.0

After a big focus on the client in the latest release, this release is more oriented towards the server.

Support for µWebSockets.js

Why should one choose between performance and reliability? Starting with [email protected], you can now use the HTTP/WebSocket server provided by the µWebSockets.js package:

const { App } = require("uWebSockets.js");
const { Server } = require("socket.io");

const app = new App();
const io = new Server();

io.attachApp(app);

io.on("connection", (socket) => {
// ...
});

app.listen(3000, (token) => {
if (!token) {
console.warn("port already in use");
}
});

It acts as a replacement for both the default Node.js HTTP server and the WebSocket server provided by the ws package, and should improve the memory footprint and the latency of your application. Benchmarks coming soon!

Emit with timeout

There is a new socket.timeout() method available on both sides:

socket.timeout(5000).emit("my-event", (err) => {
if (err) {
// the other side did not acknowledge the event in the given delay
}
});

socket.data can now be typed

For TypeScript users, the socket.data can now be typed:

interface SocketData {
name: string;
age: number;
}

const io = new Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>();

io.on("connection", (socket) => {
socket.data.name = "john";
socket.data.age = 42;
});

This release also includes some bug fixes, please see the complete diff below.

Size of the bundles:

minmin+gzip
socket.io.min.js40.4 KB (+ 0.4 KB ⬆️)13.1 KB (+ 0.1 KB ⬆️)
socket.io.msgpack.min.js45.6 KB (+ 0.4 KB ⬆️)14.2 KB (-)
socket.io.esm.min.js33.1 KB (+ 0.3 KB ⬆️)11.3 KB (+ 0.2 KB ⬆️)

That's all for this release, thanks for reading!

]]>
<![CDATA[Socket.IO 4.3.0]]> https://socket.io/blog/socket-io-4-3-0/ https://socket.io/blog/socket-io-4-3-0/ Fri, 15 Oct 2021 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We have just published a new minor version of Socket.IO: 4.3.0

An ESM bundle is now provided:

<script type="module">
import { io } from "https://cdn.socket.io/4.3.0/socket.io.esm.min.js";

const socket = io();

socket.emit("hello", "world");
</script>

The bundle size has been greatly reduced, thanks to:

  • the migration to rollup
  • the cleanup of some unused code
  • the removal of debug calls from the bundle (explanation here)

And finally, the Socket.IO client is now compatible with Vite (#1492).

Size of the bundles:

minmin+gzip
socket.io.min.js39.9 KB (-24.6 KB ⬇️)12.9 KB (-3.1 KB ⬇️)
socket.io.msgpack.min.js45.1 KB (-25.6 KB ⬇️)14 KB (-2.6 KB ⬇️)
socket.io.esm.min.js32.7 KB11.1 KB

That's all for this release, thanks for reading!

]]>
<![CDATA[Monthly update #5]]> https://socket.io/blog/monthly-update-5/ https://socket.io/blog/monthly-update-5/ Thu, 08 Jul 2021 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

Here's the #5 edition of our Monthly update.

So, what's new in the Socket.IO ecosystem?

A new API for inter-server communication

This feature had been requested for quite some time, it is now implemented in release 4.1.0. It allows to broadcast events between your Socket.IO servers.

The syntax is very similar to the existing one, except it's for server-to-server communication:

io.serverSideEmit("hello", "world");

And on the receiving side:

io.on("hello", (arg1) => {
console.log(arg1); // prints "world"
});

Acknowledgements are supported too:

// server A
io.serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // prints "pong"
});

// server B
io.on("ping", (cb) => {
cb("pong");
});

You can find the complete release notes here.

New official adapters

Historically, the Redis adapter was the only official adapter when scaling to multiple nodes.

There are now three additional official adapters:

Note: the first two were inspired from existing adapters maintained by the community and were updated to support Socket.IO v3.

All of them supports the utility methods that were added in v4, including the serverSideEmit() method described above.

Additional documentation

Version updates

What's next

  • a continuous focus on the documentation (additional code examples, extended guide, ...)
  • additional tooling around Socket.IO

Happy coding!

]]>
<![CDATA[Socket.IO 4.1.0]]> https://socket.io/blog/socket-io-4-1-0/ https://socket.io/blog/socket-io-4-1-0/ Fri, 14 May 2021 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We have just published a new minor version of Socket.IO: 4.1.0

New features

Add support for inter-server communication

This feature might be useful in a multi-server setup: you can now broadcast events between your Socket.IO servers.

Syntax:

io.serverSideEmit("hello", "world");

And on the receiving side:

io.on("hello", (arg1) => {
console.log(arg1); // prints "world"
});

Acknowledgements are supported too:

// server A
io.serverSideEmit("ping", (err, responses) => {
console.log(responses[0]); // prints "pong"
});

// server B
io.on("ping", (cb) => {
cb("pong");
});

A few notes:

// server A
io.of("/custom").serverSideEmit("sync");

// server B
io.of("/custom").on("sync", () => {
// ...
});
  • the connection, connect and new_namespace (see below) strings are reserved and cannot be used in your application.

  • you can send any number of arguments, but binary structures are currently not supported (the array of arguments will be JSON.stringify-ed)

Example:

io.serverSideEmit("hello", "world", 1, "2", { 3: "4" });

The Redis adapter and its associated emitter have been updated to support this new functionality.

Emit an event when a namespace is created

The new_namespace event will be emitted by the Server instance when a new namespace is created:

io.on("new_namespace", (namespace) => {
// ...
});

This can be useful for example:

  • to attach a shared middleware to each namespace
io.on("new_namespace", (namespace) => {
namespace.use(myMiddleware);
});
io.of(/\/nsp-\w+/);

io.on("new_namespace", (namespace) => {
console.log(namespace.name);
});

Add a way to customize the response headers

The underlying Engine.IO server, which manages the low-level connection (HTTP long-polling and/or WebSocket), will now emit two additional events:

  • initial_headers
  • headers

Like the name suggests, the initial_headers event will be emitted only for the first HTTP request of the session, while the headers event will be emitted for each HTTP request (including the WebSocket upgrade).

Example:

io.engine.on("initial_headers", (headers, req) => {
headers["test"] = "123";
headers["set-cookie"] = "mycookie=456";
});

io.engine.on("headers", (headers, req) => {
headers["test"] = "789";
});

Note: it was previously possible to achieve this by listening to the "request" event, but this should be easier with those new events:

const httpServer = require("http").createServer();
const { Server } = require("socket.io");
const io = new Server(httpServer);

httpServer.prependListener("request", (req, res) => {
res.setHeader("test", "789");
});

Add a way to get access to the reason of a connection error

The underlying Engine.IO server will also emit a new event: connection_error.

Syntax:

io.engine.on("connection_error", (err) => {
console.log(err.req); // the request object
console.log(err.code); // the error code, for example 1
console.log(err.message); // the error message, for example "Session ID unknown"
console.log(err.context); // some additional error context
});

Here is the list of possible error codes:

CodeMessage
0"Transport unknown"
1"Session ID unknown"
2"Bad handshake method"
3"Bad request"
4"Forbidden"
5"Unsupported protocol version"

Add a way to ignore the beforeunload event

A few months ago, a user reported a weird behavior when reloading a page: on Firefox, the Socket instance would emit a disconnect event, but not on Chrome or Safari.

We have published a fix for this issue in [email protected], by silently closing the connection when receiving a beforeunload event from the browser.

Unfortunately, this fix had unintended consequences: if you relied on the beforeunload event to prompt the user for confirmation ("your last modifications are not saved yet, do you really want to leave?"), the Socket.IO connection would now be closed, even if the user decided to stay on the page.

That's why we have added the closeOnBeforeunload option, to give you total control over this behavior:

const socket = io("/", {
closeOnBeforeunload: false // defaults to true
})
  • closeOnBeforeunload: true (the default value) will make all browsers behave the same (no disconnect event when reloading the page)
  • closeOnBeforeunload: false will ignore the beforeunload event, but you will get a disconnect event on Firefox

That's all for this release, thanks for reading!

]]>
<![CDATA[Monthly update #4]]> https://socket.io/blog/monthly-update-4/ https://socket.io/blog/monthly-update-4/ Thu, 06 May 2021 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

Here's the #4 edition of our Monthly update.

So, what's new in the Socket.IO ecosystem?

A new Admin UI

Following our focus on tooling, we have published a first release of the Socket.IO Admin UI:

admin UI screenshot

This Admin UI is meant to give you an overview of your Socket.IO deployment.

Here is the list of the current features:

  • overview of the servers and the clients that are currently connected
  • details of each socket instance (active transport, handshake, rooms, ...)
  • details of each room
  • administrative operations (join, leave, disconnect)

And the features which will be added in the near future:

  • overview of the number of packets/bytes sent and received per second
  • emitting an event to all clients, a room or a particular Socket instance

The installation steps can be found here.

The source code can be found here: https://github.com/socketio/socket.io-admin-ui/

If you have any feedback / suggestions, do not hesitate!

Please note that the Admin UI does support a cluster of several Socket.IO servers too.

A new guide

We have added a new guide (here), using Socket.IO to create a basic CRUD application.

Video of the application in action

Version updates

What's next

  • a continuous focus on the documentation (additional code examples, extended guide, ...)
  • additional tooling around Socket.IO

Happy coding!

]]>
<![CDATA[Socket.IO Admin UI]]> https://socket.io/blog/admin-ui-first-release/ https://socket.io/blog/admin-ui-first-release/ Fri, 16 Apr 2021 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

We have published a first release of the Socket.IO Admin UI:

admin UI screenshot

Current features:

  • overview of the servers and the clients that are currently connected
  • details of each socket instance (active transport, handshake, rooms, ...)
  • details of each room
  • administrative operations (join, leave, disconnect)

The installation steps can be found here.

The source code can be found here: https://github.com/socketio/socket.io-admin-ui/

If you have any feedback / suggestions, do not hesitate!

]]>
<![CDATA[Monthly update #3]]> https://socket.io/blog/monthly-update-3/ https://socket.io/blog/monthly-update-3/ Wed, 07 Apr 2021 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

Here's the #3 edition of our Monthly update.

So, what's new in the Socket.IO ecosystem?

Socket.IO v4

Wait, already v4?

Yes, but the upgrade should be a lot easier than from v2 to v3, since the two breaking changes only impact the API on the server side.

The most important breaking change is related to broadcasting: calling to() or any other broadcast modifier will now return an immutable object.

Previously, the modifiers were saved on the io instance directly, which could lead to surprising behaviors:

io.to("room1");
// and then later
io.to("room2").emit(/* ... */); // also sent to room1

You were also not able to reuse the operator:

const operator = io.to("room1");

operator.emit(/* ... */); // to room1 (assuming synchronous call)
operator.emit(/* ... */); // to all clients

Even more surprising, with asynchronous code:

io.to("room3").emit("details", await fetchDetails()); // unspecified behavior: maybe in room3, maybe to all clients

Starting with v4.0.0, you can now use io.to() safely:

const operator = io.to("room1").except("room2");

operator.emit(/* ... */);
operator.emit(/* ... */);

This release also brings some interesting new features, like the fetchSockets() method.

Please check the migration guide here.

Redis Adapter v6.1.0 and Redis Emitter v4.0.0

The Redis adapter (for broadcasting packets with multiple Socket.IO servers) and the Redis emitter (for broadcasting packets from another Node.js process) have been updated in order to support the new features of the v4 release.

For example, the socketsJoin method will work across Socket.IO servers:

// make all Socket instances join the "room1" room
io.socketsJoin("room1");

// make all Socket instances in the "room1" room join the "room2" and "room3" rooms
io.in("room1").socketsJoin(["room2", "room3"]);

// make all Socket instances in the "room1" room of the "admin" namespace join the "room2" room
io.of("/admin").in("room1").socketsJoin("room2");

More information can be found here.

Documentation

The documentation continues to be improved.

A new example project has been added in the "Get started" section, with middlewares and rooms: Private messaging

As usual, if you find a typo or think that some details are missing, please open an issue here: https://github.com/socketio/socket.io-website

New versions

What's next

  • a continuous focus on the documentation (additional code examples, extended guide, ...)
  • additional tooling around Socket.IO

Stay safe!

]]>
<![CDATA[Socket.IO 4.0.0]]> https://socket.io/blog/socket-io-4-release/ https://socket.io/blog/socket-io-4-release/ Wed, 10 Mar 2021 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We just published a new major version of Socket.IO: 4.0.0

Please see the associated migration guide.

TL;DR: this major bump is due to a few breaking changes at the API level.

Apart from this, the Socket.IO protocol was not updated, so a v3 client will be able to reach a v4 server and vice-versa. Besides, the compatibility mode (allowEIO3: true) is still available between a Socket.IO v2 client and a Socket.IO v4 server.

Bug Fixes (server)

  • make io.to(...) immutable (ac9e8ca)
  • set default protocol version to 3 (#616) (868d891) (Engine.IO)

Bug Fixes (client)

  • bundle: restore support for JS modules (43613d1)

Features (server)

  • add some utility methods (b25495c)
  • add support for typed events (#3822) (0107510)
  • allow to exclude specific rooms when broadcasting (#3789) (7de2e87)
  • allow to pass an array to io.to(...) (085d1de)
  • increase the default value of pingTimeout (5a7fa13) (Engine.IO)
  • remove dynamic require() with wsEngine (edb7343) (Engine.IO)

Features (client)

  • add autoUnref option (6abfa1f)
  • add support for typed events (5902365)
  • listen to the "offline" event (c361bc6) (Engine.IO client)
]]>
<![CDATA[Socket.IO 3.1.0]]> https://socket.io/blog/socket-io-3-1-0/ https://socket.io/blog/socket-io-3-1-0/ Fri, 15 Jan 2021 00:00:00 GMT <![CDATA[Hello everyone!]]> <![CDATA[

Hello everyone!

We just published a new version of Socket.IO: 3.1.0

In order to ease the migration to Socket.IO v3, the v3 server is now able to communicate with v2 clients:

const io = require("socket.io")({
allowEIO3: true // false by default
});

This should make the migration easier for existing deployments:

  • first, update the servers with allowEIO3 set to true
const io = require("socket.io")({
allowEIO3: true // false by default
});

Note: If you are using the Redis adapter to broadcast packets between nodes, you must use socket.io-redis@5 with socket.io@2 and socket.io-redis@6 with socket.io@3. Please note that both versions are compatible, so you can update each server one by one (no big bang is needed).

  • then, update the clients

This step may actually take some time, as some clients may still have a v2 client in cache.

You can check the version of the connection with:

io.on("connection", (socket) => {
const version = socket.conn.protocol; // either 3 or 4
});

This matches the value of the EIO query parameter in the HTTP requests.

  • and finally, once every client was updated, set allowEIO3 to false (which is the default value)
const io = require("socket.io")({
allowEIO3: false
});

With allowEIO3 set to false, v2 clients will now receive an HTTP 400 error (Unsupported protocol version) when connecting.

The migration guide was updated accordingly.

Features

Bug Fixes

]]>
<![CDATA[Socket.IO 2.4.0]]> https://socket.io/blog/socket-io-2-4-0/ https://socket.io/blog/socket-io-2-4-0/ Tue, 05 Jan 2021 00:00:00 GMT <![CDATA[Happy New Year everyone!]]> <![CDATA[

Happy New Year everyone!

We just published a new minor version in the 2.x branch!

Please note that this release contains a breaking change regarding Cross-Origin Resource Sharing (CORS).

UPDATE: this change was reverted in 2.4.1, because it did not follow semantic versioning and broke some deployments (discussed here). Please make sure you are properly securing your application, and upgrade to Socket.IO v3 as soon as possible.

Previously, CORS was enabled by default, which meant that a Socket.IO server sent the necessary CORS headers (Access-Control-Allow-xxx) to any domain. This will not be the case anymore, and you now have to explicitly enable it.

Please note that you are not impacted if:

  • you are using Socket.IO v2 and the origins option to restrict the list of allowed domains
  • you are using Socket.IO v3 (disabled by default)

This change also removes the support for '*' matchers and protocol-less URL:

io.origins('https://example.com:443'); => io.origins(['https://example.com']);
io.origins('localhost:3000'); => io.origins(['http://localhost:3000']);
io.origins('http://localhost:*'); => io.origins(['http://localhost:3000']);
io.origins('*:3000'); => io.origins(['http://localhost:3000']);

To restore the previous behavior (please use with caution):

io.origins((_, callback) => {
callback(null, true);
});

A big thanks to @ni8walk3r for the detailed security report.

See also:

Features

  • add support for all cookie options (19cc582)
  • disable perMessageDeflate by default (5ad2736)

Bug Fixes

  • security: do not allow all origins by default (f78a575)
  • properly overwrite the query sent in the handshake (d33a619)

Stay safe!

]]>
<![CDATA[Monthly update #2]]> https://socket.io/blog/monthly-update-2/ https://socket.io/blog/monthly-update-2/ Mon, 23 Nov 2020 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

Here's the #2 edition of our Monthly update. This is a new experiment, we will try to stick to this frequency in order to keep you updated of the work in progress and the directions the project is taking.

So, what's new in the Socket.IO ecosystem?

Socket.IO v3

As announced in the previous monthly update, Socket.IO v3 has been released a few days ago.

This major version bump is mandated by several necessary changes in the Engine.IO protocol. You can find more information about these changes in the Engine.IO v4 release notes.

You can find the release notes here and the migration guide here.

Let's discuss about this release here: https://github.com/socketio/socket.io/discussions/3674

Redis Adapter v6

Following the release of Socket.IO v3.0.0, the Redis Adapter was updated and a new release is out: 6.0.0

You can find the release notes here.

Documentation

The documentation has always been a weak point of the project, leading to a lot of issues opened on GitHub and questions on StackOverflow.

Now that v3 is out, we will focus on this. The following pages have already been created:

If you find a typo, please open an issue here: https://github.com/socketio/socket.io-website

Minor bumps

More information about how to use those custom parsers can be found here.

What's next

  • the client implementations in other languages will be updated as well

  • a big focus on the documentation (additional code examples, extended guide, ...)

  • additional tooling around Socket.IO

Stay safe!

]]>
<![CDATA[Redis Adapter v6.0.0]]> https://socket.io/blog/socket-io-redis-adapter-6-release/ https://socket.io/blog/socket-io-redis-adapter-6-release/ Thu, 12 Nov 2020 00:00:00 GMT <![CDATA[Following the release of Socket.IO v3.0.0, the Redis Adapter was updated and a new release is out: 6.0.0]]> <![CDATA[

Following the release of Socket.IO v3.0.0, the Redis Adapter was updated and a new release is out: 6.0.0

For reference, the Redis Adapter is used when broadcasting packets across a set of Socket.IO servers. It relies on Redis Pub/Sub mechanism.

More information about how it works: https://github.com/socketio/socket.io-redis/#how-does-it-work-under-the-hood

The release notes can be found here: https://github.com/socketio/socket.io-redis/releases/tag/6.0.0

Please note that the new release is not compatible with Socket.IO v2, and previous versions are not compatible with Socket.IO v3 (compatibility table).

Notable changes

All the requests (for inter-node communication) now return a Promise instead of accepting a callback

The Redis Adapter exposes additional methods for managing sockets and rooms in a multi-node setup:

  • RedisAdapter.sockets(): returns the list of Socket IDs
  • RedisAdapter.allRooms(): returns the list of all rooms.
  • RedisAdapter.remoteJoin(id, room): make the socket join the room
  • RedisAdapter.remoteLeave(id, room): make the socket leave the room
  • RedisAdapter.remoteDisconnect(id, close): disconnect the socket with the given id

Those methods used to accept a callback argument, they will now return a Promise.

Before:

io.of('/').adapter.allRooms((err, rooms) => {
console.log(rooms); // an array containing all rooms (across all nodes)
});

After:

const rooms = await io.of('/').adapter.allRooms();
console.log(rooms); // a Set containing all rooms (across all nodes)

customHook and customRequest methods were removed

Those methods will be replaced by a more intuitive API in a future iteration.

]]>
<![CDATA[Socket.IO 3 Release]]> https://socket.io/blog/socket-io-3-release/ https://socket.io/blog/socket-io-3-release/ Thu, 05 Nov 2020 00:00:00 GMT <![CDATA[We are happy to announce the release of Socket.IO v3!]]> <![CDATA[

We are happy to announce the release of Socket.IO v3!

Migration guide

This release contains a few non backward compatible changes.

We have published a dedicated migration guide with all necessary details.

Why Socket.IO in 2020?

That's an excellent question actually. Depending on your use case, it might make sense to use plain WebSocket directly:

What Socket.IO brings:

  • a fallback to HTTP long-polling, in case the WebSocket connection cannot be established

To be honest, this feature was awesome 10 years ago, when most browsers didn't support WebSocket, but this is not the case anymore. That's still a great safety net though.

  • auto-reconnection

Using plain WebSocket, you can take a look at robust-websocket.

  • a classic request-response API: acknowledgements
// on one side
socket.emit("updateitem", "1", { name: "updated" }, (response) => {
console.log(response.status); // ok
});
// on the other
socket.on("updateitem", (arg1, arg2, callback) => {
console.log(arg1); // 1
console.log(arg2); // { name: "updated" }
callback({
status: "ok"
});
});
  • a way to broadcast data to a given set of clients: Rooms
// server-side
io.on("connection", (socket) => {
socket.join("room1");

io.to("room1").emit("hello!");
});

Which also works when scaling to several Socket.IO servers (more information here).

  • a way to split your application logic into distinct modules (for more complex applications): Namespaces
// server-side
const adminNamespace = io.of("/admin");

adminNamespace.use((socket, next) => {
// ensure the socket is authorized
});

adminNamespace.on((socket) => {
socket.on("delete project", (id) => {
// in all handlers, we are sure that the socket is authorized
});
});

adminNamespace.emit("hello!"); // broadcast to admin only

What's next

  • the Redis adapter (used when broadcasting across Socket.IO servers) will be updated in order to be compatible with Socket.IO v3 (update: done!)

  • the client implementations in other languages will be updated as well

  • a big focus on the documentation (additional code examples, extended guide, ...)

  • additional tooling around Socket.IO

Let's discuss!

The project is now part of the beta of Github Discussions. Depending on the feedback of the community, it might replace the Slack channel in the future.

If you have any question about the release, let's discuss here.

Stay safe!

]]>
<![CDATA[Monthly update #1]]> https://socket.io/blog/monthly-update-1/ https://socket.io/blog/monthly-update-1/ Sat, 03 Oct 2020 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

Here's the #1 edition of our Monthly update. This is a new experiment, we will try to stick to this frequency in order to keep you updated of the work that is in progress and the directions the project is taking.

So, what's new in the Socket.IO ecosystem?

Socket.IO v3 (WIP)

The work on Socket.IO v3 has started (let's be honest and not say resumed).

This major version bump is mandated by several necessary changes in the Engine.IO protocol. You can find more information about these changes in the Engine.IO v4 release notes.

It mostly impacts the way packets are encoded when sent over the wire (in the request/response body in case of HTTP long-polling, or in the WebSocket frames), so the public API of Socket.IO should not be impacted that much.

We will also take advantage of this new version to migrate the codebase to Typescript, so the typings which are currently hosted in the DefinitelyTyped will now always be in sync with the actual code.

You can follow the progress here.

If you have any feedback/feature that you would like to see included, please comment here.

Engine.IO v4

As part of the work towards Socket v3, Engine.IO v4 has been released.

The list of breaking changes can be found in the release notes.

Protocol documentation

The documentation of the Engine.IO and the Socket.IO protocols has been edited with additional details/examples.

This should help greatly when implementing a client in another programming language.

If you find that something is not clear/is missing, please open an issue in the repository.

For reference, here's the current list of clients in other languages:

GitHub discussions

The project is now part of the beta of Github Discussions. Depending on the feedback of the community, it might replace the Slack channel in the future.

So, let's discuss!

Minor bumps

More information about how to use those custom parsers can be found here.

Going forward

As announced at the bottom of the Engine.IO v4 release notes, I (@darrachequesne) am now dedicated full time to the project since the beginning of September. This wouldn't be possible without our sponsors, so again, a big thanks to them!

Stay safe!

]]>
<![CDATA[Socket.IO client 2.3.1]]> https://socket.io/blog/socket-io-2-3-1/ https://socket.io/blog/socket-io-2-3-1/ Fri, 02 Oct 2020 00:00:00 GMT <![CDATA[Hi everyone!]]> <![CDATA[

Hi everyone!

We have published a minor version of the client: 2.3.1

The debug dependency has been reverted to ~3.1.0, as the newer versions contains ES6 syntax which breaks in IE browsers.

Please note that this only applied to users that bundle the Socket.IO client in their application, with webpack for example, as the "official" bundles (in the dist/ folder) were already transpiled with babel.

For webpack users, you can also take a look at the webpack-remove-debug plugin.

Bug Fixes

  • fix reconnection after opening socket asynchronously (#1253) (050108b)

Get the latest client from the CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.1/socket.io.slim.js"></script>

For an explanation between the different bundles, please see here.

Stay safe!

]]>
<![CDATA[Engine.IO 4 Release]]> https://socket.io/blog/engine-io-4-release/ https://socket.io/blog/engine-io-4-release/ Thu, 10 Sep 2020 00:00:00 GMT <![CDATA[We are happy to announce the release of Engine.IO v4, the low-level engine that powers Socket.IO.]]> <![CDATA[

We are happy to announce the release of Engine.IO v4, the low-level engine that powers Socket.IO.

Major breaking changes

Heartbeat mechanism reversal

We have received a lot of reports from users that experience random disconnects due to ping timeout, even though their Internet connection is up and the remote server is reachable. It should be noted that in that case the client reconnects right away, but still it was an annoying issue.

After analysis, it seems to be caused by delayed timers on the client-side. Those timers are used in the ping-pong mechanism which helps to ensure the connection between the server and the client is still healthy. A delay on the client-side meant the client sent the ping packet too late, and the server considered that the connection was closed.

That's why the ping packets will now be sent by the server, and the client will respond with a pong packet.

Packet encoding

We have also changed the way the data is encoded. It previously relied on the string length in Javascript, which meant it was harder to implement clients in other programming languages that do not share the same encoding (more details here).

Technically speaking, it impacts the way an array of packets is encoded when using XHR polling (WebSocket is not affected, as each packet is sent in its own WebSocket frame).

socket.send("€€");
socket.send("й");

// v3 encoding output
"3:4€€2:4й"

// 3 "4€€".length (the JS specific part, 6 bytes)
// : separator
// 4 the "message" packet type
// €€ the content of the first packet
// 2 "4й".length (again, the JS specific part)
// : separator
// 4 the "message" packet type
// й the content of the second packet

// v4 encoding output
"4€€\x1e4й"

// 4 the "message" packet type
// €€ the content of the first packet
// \x1e separator
// 4 the "message" packet type
// й the content of the second packet

You can find more details about the updates to the protocol here.

Other changes

CORS handling

We now use the cors package to handle the CORS configuration. The handlePreflightRequest option was removed:

const { Server } = require('engine.io');

// before
new Server({
handlePreflightRequest: (req, res) => {
res.writeHead(200, {
"Access-Control-Allow-Origin": 'https://example.com',
"Access-Control-Allow-Methods": 'GET',
"Access-Control-Allow-Headers": 'Authorization',
"Access-Control-Allow-Credentials": true
});
res.end();
}
});

// after
new Server({
cors: {
origin: "https://example.com",
methods: ["GET"],
allowedHeaders: ["Authorization"],
credentials: true
}
});

Please see here for all available options.

In Engine.IO v3, the io cookie was sent by default. This cookie can be used to enable sticky-session, which is required when you have several servers (more information here).

However, this cookie is not needed in some cases (i.e. single server deployment, sticky-session based on IP) so it must now be explicitly enabled:

const { Server } = require('engine.io');

// before
new Server({
cookieName: "io",
cookieHttpOnly: false,
cookiePath: "/custom"
});

// after
new Server({
cookie: {
name: "test",
httpOnly: false,
path: "/custom"
}
});

All other options (domain, maxAge, sameSite, ...) are now supported. Please see here for the complete list of options.

The default value of maxHttpBufferSize was decreased

This option defines how many bytes or characters a message can be, before closing the connection. It was reduced from 100MB to 1MB.

const { Server } = require('engine.io');

new Server({
maxHttpBufferSize: 1e8 // defaults to 1e6
});

perMessageDeflate is now disabled by default

This option defines whether the WebSocket permessage-deflate extension is enabled or not. This feature, while useful in some cases, adds some extra memory overhead for each WebSocket connection, and could result in huge memory usage in production deployments. It is now disabled by default.

const { Server } = require('engine.io');

new Server({
perMessageDeflate: true // defaults to false
});

Support for Node.js 8 was dropped

We are dropping support for Node.js 8, which is now End-of-Life. It will not be tested in the CI anymore, so please upgrade as soon as possible!

How to upgrade

As detailed in the Major breaking changes section, this release contains several backward incompatible changes, and as such v3 clients will not be able to connect to a v4 server (and vice versa).

In order to upgrade a live production environment, you will need to have both a group of v3 servers and v4 servers in parallel, and route the traffic based on either:

  • the EIO query parameter
  • the path (by using a different path for the v4 servers)
  • or the domain if you use a different domain for the v4 servers

So that it shall be a seamless migration for your end users.

What's next

This release will be included in Socket.IO v3 in the near future. We will publish a more detailed roadmap in the next blog post.

Besides, I (@darrachequesne) am glad to announce that I will be dedicated full time to the project for the next months. This is possible thanks to our awesome sponsors.

Again, a big shout out to Pia Mancini and all the team behind the Open Collective platform, which helps making Open Source Software sustainable in the long term.

Let's discuss!

The project is now part of the beta of Github Discussions. Depending on the feedback of the community, it might replace the Slack channel in the future.

If you have any question about the release, let's discuss about it here.

Stay safe!

]]>
<![CDATA[Socket.IO 2.0.1, 2.0.2 and 2.0.3]]> https://socket.io/blog/socket-io-2-0-1-2-0-2-and-2-0-3/ https://socket.io/blog/socket-io-2-0-1-2-0-2-and-2-0-3/ Sat, 24 Jun 2017 00:00:00 GMT <![CDATA[We published three minor releases right after 2.0.0, so please be sure to use the latest version!]]> <![CDATA[

We published three minor releases right after 2.0.0, so please be sure to use the latest version!

Including:

  • A fix for a race condition within middleware: Issue #2935

  • A fix for a potential race condition when emitting to a room: Issue #2962

  • A fix for the query option in the client: Issue #1086

Get the latest client from the CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
]]>
<![CDATA[Socket.IO is on Open Collective]]> https://socket.io/blog/socket-io-is-on-open-collective/ https://socket.io/blog/socket-io-is-on-open-collective/ Mon, 15 May 2017 00:00:00 GMT <![CDATA[Open Collective provides a transparent, sustainable, and secure way for people to support and sponsor open source projects. We are joining other great projects (you may have heard about MochaJS, GulpJS or webpack, among lots of other awesome projects) in the quest to ensure the project's sustainability.]]> <![CDATA[

Open Collective provides a transparent, sustainable, and secure way for people to support and sponsor open source projects. We are joining other great projects (you may have heard about MochaJS, GulpJS or webpack, among lots of other awesome projects) in the quest to ensure the project's sustainability.

What is an Open Collective?

From their website:

An Open Collective is a group of people with a shared mission that operates in full transparency.

That allows both individuals and companies to sponsor our mission at Socket.IO (with potential tax benefits).

What would Socket.IO do with my sponsorship?

That will enable the core contributors to spend more time assuring the maintenance of the project. That includes:

  • triaging issues and pull requests

  • answering questions on Slack and Stackoverflow (which have been somewhat neglected recently)

  • updating the documentation (I think a lot has been done recently, but there is still room for improvement!)

Personally I would like to be able to devote a few days a month to the project (I mean a whole day of work, not a few hours taken here and there, usually late in the evening).

The goals in the near future:

  • keep the 2.0 version as stable as possible
  • provide a complete documentation
  • add more examples, besides the classic chat

How can I help?

To become a sponsor or backer, visit our open collective page and follow the instructions for becoming a part of our collective. Please also take the time to explore the other awesome collectives that people are supporting.

And finally, a big thanks to Pia Mancini and her partners for making this possible.

]]>
<![CDATA[Socket.IO 2.0.0]]> https://socket.io/blog/socket-io-2-0-0/ https://socket.io/blog/socket-io-2-0-0/ Sat, 13 May 2017 00:00:00 GMT <![CDATA[Socket.IO 2.0.0 is finally here!]]> <![CDATA[

Socket.IO 2.0.0 is finally here!

This major release brings several performance improvements:

  • uws is now the default Websocket engine. It should bring significant improvement in performance (particularly in terms of memory consumption) (release note of Engine.IO)

  • the Engine.IO and Socket.IO handshake packets were merged, reducing the number of roundtrips necessary to establish a connection. (#2833)

  • it is now possible to provide a custom parser according to the needs of your application (#2829). Please take a look at the example for more information.

Please note that this release is not backward-compatible, due to:

  • a breaking change related to utf-8 encoding in engine.io-parser

  • an update to make the socket id on the client match the id on the server-side (#1058)

Related packages were updated accordingly:

  • socket.io-redis version 5.x

  • socket.io-emitter version 3.x

Get the latest client from the CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.1/socket.io.js"></script>
]]>
<![CDATA[Socket.IO 1.4.5]]> https://socket.io/blog/socket-io-1-4-5/ https://socket.io/blog/socket-io-1-4-5/ Wed, 27 Jan 2016 00:00:00 GMT <![CDATA[We just published some quick fixes!]]> <![CDATA[

We just published some quick fixes!

  • Fixed socket.io-client usage with NativeScript.
  • Fixed graceful close of the attached http Server of socket.io and engine.io.

Get the latest client from the CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.5/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.4.4]]> https://socket.io/blog/socket-io-1-4-4/ https://socket.io/blog/socket-io-1-4-4/ Mon, 11 Jan 2016 00:00:00 GMT <![CDATA[We just published two fixes for socket.io-client:]]> <![CDATA[

We just published two fixes for socket.io-client:

  • Building with browserify or webpack is now completely straightforward. No need to exclude/ignore or noParse/externals the ws module.

  • Improved the JSONP transport when socket.io-client or engine.io-client are lazily evaluated or the <script> tag that included them gets removed.

Get the latest client from the CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.4/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.4.1, 1.4.2 and 1.4.3]]> https://socket.io/blog/socket-io-1-4-1-1-4-2-and-1-4-3/ https://socket.io/blog/socket-io-1-4-1-1-4-2-and-1-4-3/ Fri, 08 Jan 2016 00:00:00 GMT <![CDATA[We published three minor releases right after 1.4.0 addressing build issues in different environments.]]> <![CDATA[

We published three minor releases right after 1.4.0 addressing build issues in different environments.

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.3/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.4.0]]> https://socket.io/blog/socket-io-1-4-0/ https://socket.io/blog/socket-io-1-4-0/ Wed, 06 Jan 2016 00:00:00 GMT <![CDATA[Socket.IO 1.4.0 ship with new features like automatic compression for XHR and WebSockets, lots of bug fixes and significant performance and memory improvements.]]> <![CDATA[

Socket.IO 1.4.0 ship with new features like automatic compression for XHR and WebSockets, lots of bug fixes and significant performance and memory improvements.

Compression is enabled by default, as it’s highly beneficial for most application payloads. The following example shows the savings for a realtime stream of tweets.

The compression gains will vary by transport. For example, WebSocket defaults to a window size of 32kb when DEFLATE compression is enabled. Repeated occurrences of strings within that window will be compressed. The following demo (inspired by Julia Evans work) will highlight what the LZ77 algorithm de-duplicates from the traffic sent by the Twitter stream that matches javascript.

How this demo works: we re-implemented a part of LZ77 in JavaScript. A React component then renders the compressed strings.

The longer the string, the darker the shade of yellow displayed.

In addition to this default behavior, we’ve introduced the capability to perform selective per-message compression, by introducing the compress flag when emitting an event.

socket.compress(true).emit(‘hi’, { some: ‘data’ });

To configure the defaults, we’ve introduced the following two options that you can pass to socket.io (and engine.io) when starting the server:

  • perMessageDeflate – options to customize WebSocket compression (see here) or true for defaults (true).

  • httpCompression – options to customize compression for HTTP polling transports or true for defaults (true)

The memory overhead when compression is enabled is not inexistent, however. Make sure to account for a 300kb~ overhead per connection in terms of memory allocation. Read here about the parameters you can customize to change how much memory is allocated and how aggressively data is compressed.

The following improvements have been made to the server:

  • Assume 443 port when passing https:// to the origins parameter – Evan Lucas
  • Improve detection of binary data inside events (in the has-binary module) – Gunther Brunner
  • Warn about missing error event handlers on sockets to prevent silent hard-to-debug situations
  • Allow a custom function for the allowRequest function for origins verification
  • Fixes for “use strict” environments – Naoyuki Kanezawa
  • Prevent users calling the ack function multiple times – Kevin Jose Martin
  • Fixed potential memory leaks with open sockets when upgrade fails – Naoyuki Kanezawa
  • Fix lingering requests when a polling error occurs – Naoyuki Kanezawa
  • Drastically more memory efficient when keeping track of clients – Damien Arrachequesne
  • Drastically more memory efficient when keeping track of rooms – Jérémy Lal
  • Trigger callback if the client is already in the given room when join is called – Damien Arrachequesne
  • Minor parser fixes and performance improvements.

The following improvements have been made to the client:

  • Fix for specifying custom ports when connecting
  • 2 or more connections to the same namespace now create new sockets, instead of reusing a single one.
  • Added new reserved ping and pong events when a heartbeat is emitted and received.
  • Add support for environments that extend Object.prototype – Damien Arrachequesne
  • Fixes for “use strict” environments – Naoyuki Kanezawa
  • Added an extraHeaders feature for custom headers in HTTP transports (non-WebSocket)
  • Fix handling of disconnection while in the opening state.
  • Improved error handling for unmatched acknowledgements.
  • Parser fixes and improvements.

We've also released socket.io-redis 0.2.0 with significant performance improvements.

Special thanks to Damien Arrachequesne, Naoyuki Kanezawa and Jérémy Lal for their amazing and continued contributions that made this release possible.

]]>
<![CDATA[Socket.IO 1.3.7]]> https://socket.io/blog/socket-io-1-3-7/ https://socket.io/blog/socket-io-1-3-7/ Mon, 21 Sep 2015 00:00:00 GMT <![CDATA[Socket.IO 1.3.7 includes support for io.js and Node.JS 4.0.0.]]> <![CDATA[

Socket.IO 1.3.7 includes support for io.js and Node.JS 4.0.0.

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.3.6]]> https://socket.io/blog/socket-io-1-3-6/ https://socket.io/blog/socket-io-1-3-6/ Wed, 15 Jul 2015 00:00:00 GMT <![CDATA[Socket.IO 1.3.6 addresses a build issue with the ws module on Windows.]]> <![CDATA[

Socket.IO 1.3.6 addresses a build issue with the ws module on Windows.

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO P2P]]> https://socket.io/blog/socket-io-p2p/ https://socket.io/blog/socket-io-p2p/ Tue, 14 Jul 2015 00:00:00 GMT <![CDATA[Today were very happy to introduce Socket.IO P2P, the easiest way to establish a bidirectional events channel between two peers with a server fallback to provide maximum reliability.]]> <![CDATA[

Today were very happy to introduce Socket.IO P2P, the easiest way to establish a bidirectional events channel between two peers with a server fallback to provide maximum reliability.

Lets look at the API and build a little chat application. Or check out the repository directly!

Socket.IO P2P provides an easy and reliable way to setup a WebRTC connection between peers and communicate using the socket.io-protocol.

Socket.IO is used to transport signaling data and as a fallback for clients where the WebRTC PeerConnection is not supported. Adding a simple piece of middleware to your socket.io setup enables this – no need to hand roll your own signaling exchange or set up, deploy and scale new servers.

Usage

It only takes a few lines of code to set up the server and client.

Server:

var io = require('socket.io')(server);
var p2p = require('socket.io-p2p-server').Server;
io.use(p2p);

Client:

var P2P = require('socket.io-p2p');
var io = require('socket.io-client');
var socket = io();
var p2p = new P2P(socket);
p2p.on('peer-msg', function (data) {
console.log('From a peer %s', data);
});

There are various options for the advanced user. Once signaling data has been exchanged an upgrade event is triggered and an optional callback is called.

var opts = { numClients: 10 }; // connect up to 10 clients at a time
var p2p = new P2P(socket, opts, function(){
console.log('We all speak WebRTC now');
});

The Chat example

We will build a simple chat application, as our tradition dictates, but with P2P capabilities! In this application:

  • Clients can send text messages to each other. Messages display in a timeline
  • Clients connect to each other over socket.io and initially send messages via the server
  • Clients can choose to go private – switching the transport to WebRTC
  • All clients connected to the server can connect via WebRTC up to a maximum of 10 clients

All code from this example is included in the main repository.

We first setup the client with autoUpgrade set to false so that clients can upgrade the connection themselves. Set numClients to 10 to allow up to 10 clients to connect with each other.

var opts = {autoUpgrade: false, numClients: 10};
var p2psocket = new P2P(socket, opts)

Setup the event listeners:

p2psocket.on('peer-msg', function(data) {
// append message to list
});

p2psocket.on('go-private', function () {
p2psocket.upgrade(); // upgrade to peerConnection
});

In this example, we want any clients connecting to the server to exchange signaling data with each other. We can use the server component as a simple middleware. Clients will connect on the root namespace.

If we wanted clients to exchange signalling data in rooms, rather than on a whole namespace, we could use the server module upon connection like this.

var server = require('http').createServer();
var p2pserver = require('socket.io-p2p-server').Server
var io = require('socket.io')(server);
server.listen(3030)
io.use(p2pserver);

We then setup listeners to pass messages between clients and to broadcast the go-private event.

io.on('connection', function(socket) {
socket.on('peer-msg', function(data) {
console.log('Message from peer: %s', data);
socket.broadcast.emit('peer-msg', data);
})

socket.on('go-private', function(data) {
socket.broadcast.emit('go-private', data);
});
});

Thats all you need: add a little markup we are off! Heres the demo application in action:

P2PChatExampleRedo2

Thanks to Guillermo Rauch (@rauchg) for the advice, testing and patience, Harrison Harnisch (@hharnisc) for bug fixes and to Feross Aboukhadijeh (@feross) for providing the underlying WebRTC abstraction simple-peer.

Pull requests, issues, comments and general rantings are all welcome over at the GitHub repo.

]]>
<![CDATA[Socket.IO C++]]> https://socket.io/blog/socket-io-cpp/ https://socket.io/blog/socket-io-cpp/ Mon, 13 Apr 2015 00:00:00 GMT <![CDATA[I'm really proud to announce the first release of the Socket.IO C++ Client on GitHub!]]> <![CDATA[

I'm really proud to announce the first release of the Socket.IO C++ Client on GitHub!

Based on Boost and WebSocket++, this full-featured Socket.IO 1.0 client has the fundamental advantage of working on multiple platforms. Check out the directory of examples. It contains examples of iOS, QT, and CLI chat clients!

To learn how to use this client, I put together a QT chat example that communicates using a Socket.IO Node.JS chat server. Keep reading for step-by-step instructions.

Introduction

If you’d like to follow along, begin by cloning the socket.io-client-cpp repository using the following:

git clone --recurse-submodules https://github.com/socketio/socket.io-client-cpp.git

The app includes the following features:

  • Send messages to all users joining the room.
  • Receive a notification when users join or leave the room.
  • Receive notifications when a user starts typing a message.

Before you get started, visit the QT community to download and install QT.

Creating a QT GUI Application

Launch the QT Creator.

On the welcome page, select New Project, then create a QT Widget Application. Name it SioChatDemo.

The project structure should look like this:

SioChatDemo
|__ SioChatDemo.pro
|__Headers
| |__mainwindow.h
|__Sources
| |__main.cpp
| |__mainwindow.cpp
|__Forms
|__mainwindow.ui

Importing an SioClient

Lets copy the SioClient into the QT project under the subfolder sioclient.

Edit SioChatDemo.pro to configure paths and compile options by simply adding:

SOURCES += ./sioclient/src/sio_client.cpp
./sioclient/src/sio_packet.cpp

HEADERS += ./sioclient/src/sio_client.h
./sioclient/src/sio_message.h

INCLUDEPATH += $$PWD/sioclient/lib/rapidjson/include
INCLUDEPATH += $$PWD/sioclient/lib/websocketpp

Add two additional compile options:

CONFIG+=no_keywords
CONFIG+=c++11

The no_keywords flag prevents qmake from treating some function names as emit as the keyword for the signal-slot mechanism.

Use c++11 to ask for C++11 support.

Importing Boost

We now have our boost headers and a fat boost static lib named libboost.a(non-win32) or boost.lib(win32).

To import them, we need to edit SioChatDemo.pro again by adding a header including the following:

INCLUDEPATH += `our boost headers folder`

Linker options:

win32:CONFIG(release, debug|release): LIBS += -L`our Win32 boost static lib folder` -lboost
else:win32:CONFIG(debug, debug|release): LIBS += -L`our Win32 boost static lib folder` -lboost
else:unix: LIBS += -L`our osx boost static lib folder` -lboost

Create the Main Window UI

Create a simple UI by dragging and dropping a widget from the widget box on the left-hand side.

It contains the following:

  • A QLineEdit at the top to input a nickname: nickNameEdit
  • A QPushButton at the top right for login: loginBtn
  • A QListWidget in the center for showing messages: listView
  • A QLineEdit at the bottom for typing messages: messageEdit
  • A QPushButton at the bottom right for sending messages: sendBtn

Add Slots in the Main Window

The following slots need to be added in the mainwindow class to handle UI events:

  • Click ‘Login’ button
  • Click ‘Send Message’ button
  • Text change in message editing (to show typing status)
  • Return message editing (for sending responses)

Insert the following code into the MainWindow class in mainwindow.h:

public Q_SLOTS:
void SendBtnClicked();
void TypingChanged();
void LoginClicked();
void OnMessageReturn();

Connect the UI Event Signal and Slots

Open mainwindow.ui in the design mode. Switch to the signals/slots mode using Menu->Edit->Edit Signals/Slots.

Click and hold the widget and drag it to the window (the cursor will become an electrical ground symbol) to open the connection editor.

In the connection editor, edit the main window slots on the right side. Add the slot function names added in mainwindow.h before.

Then we can connect the event signal to the widget with our own slots. The result should look like this:

Adding UI Refresh Signals/Slots

The sio::client callbacks are not in the UI thread. However, the UI must be updated with those callbacks, so we need a signal for the non-UI thread to request the slots functions in the UI thread. To signal that QListWidgetItem has been added, insert the following:

// in mainwindow.h
Q_SIGNALS:
void RequestAddListItem(QListWidgetItem *item);
private Q_SLOTS:
void AddListItem(QListWidgetItem *item);
//In mainwindow.cpp
void MainWindow::AddListItem(QListWidgetItem* item)
{
this->findChild<QListWidget*>("listView")->addItem(item);
}

Then connect them in the MainWindow constructor.

connect(this,SIGNAL(RequestAddListItem(QListWidgetItem*)),this,SLOT(AddListItem(QListWidgetItem*)));

Setting up the Socket

For single-window applications, simply let MainWindow class hold the sio::client object by declaring a unique_ptr member of the sio::client and several event handling functions in mainwindow.h.

private:
void OnNewMessage(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnUserJoined(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnUserLeft(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnTyping(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnStopTyping(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnLogin(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp);
void OnConnected();
void OnClosed(client::close_reason const& reason);
void OnFailed();

std::unique_ptr<client> _io;

Initialize sio::client and setup event bindings for the default socket in the MainWindow constructor.

We also need to handle connectivity and disconnect events.

Add the following to the MainWindow constructor:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
_io(new client())
{
ui->setupUi(this);
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
socket::ptr sock = _io->socket();
sock->on("new message",std::bind(&MainWindow::OnNewMessage,this,_1,_2,_3,_4));
sock->on("user joined",std::bind(&MainWindow::OnUserJoined,this,_1,_2,_3,_4));
sock->on("user left",std::bind(&MainWindow::OnUserLeft,this,_1,_2,_3,_4));
sock->on("typing",std::bind(&MainWindow::OnTyping,this,_1,_2,_3,_4));
sock->on("stop typing",std::bind(&MainWindow::OnStopTyping,this,_1,_2,_3,_4));
sock->on("login",std::bind(&MainWindow::OnLogin,this,_1,_2,_3,_4));
//default socket opened, also we have "set_open_listener" for monitoring physical connection opened.
_io->set_socket_open_listener(std::bind(&MainWindow::OnConnected,this,std::placeholders::_1));
//physical connection closed or drop.
_io->set_close_listener(std::bind(&MainWindow::OnClosed,this,_1));
//physical connection fail to establish.
_io->set_fail_listener(std::bind(&MainWindow::OnFailed,this));
connect(this,SIGNAL(RequestAddListItem(QListWidgetItem*)),this,SLOT(AddListItem(QListWidgetItem*)));
}

Managing Connection State

We have several connection listeners for connection events.

First, we want to send a login message when were connected; we get the default socket from the client to do that.

void MainWindow::OnConnected()
{
QByteArray bytes = m_name.toUtf8();
std::string nickName(bytes.data(),bytes.length());
_io->socket()->emit("add user", nickName);
}

If the connection closes or fails, we need to restore the UI before we connect.

void MainWindow::OnClosed(client::close_reason const& reason)
{
//restore UI to pre-login state
}

void MainWindow::OnFailed()
{
//restore UI to pre-login state
}
```

If we exit the `MainWindow`, we need to clear the event bindings and listeners.

The `sio::client` object will be destroyed using `unique_ptr`.

```cpp
MainWindow::~MainWindow()
{
_io->socket()->off_all();
_io->socket()->off_error();
delete ui;
}
```

## Handling Socket.IO Events

We'll need to handle socket.io events in our functions they are bound to.

For example, we need to show received messages in the list view.

```cpp
void MainWindow::OnNewMessage(std::string const& name,message::ptr const& data,bool hasAck,message::ptr &ack_resp)
{
if(data->get_flag() == message::flag_object)
{
std::string msg = data->get_map()["message"]->get_string();
std::string name = data->get_map()["username"]->get_string();
QString label = QString::fromUtf8(name.data(),name.length());
label.append(':');
label.append(QString::fromUtf8(msg.data(),msg.length()));
QListWidgetItem *item= new QListWidgetItem(label);
//emit RequestAddListItem signal
//so that 'AddListItem' will be executed in UI thread.
Q_EMIT RequestAddListItem(item);
}
}
```

## Wrapping Up: Sending the Message

When `sendBtn` is clicked, we need to send the text in `messageEdit` to the chatroom.

Add the following code to `SendBtnClicked()`:

```cpp
void MainWindow::SendBtnClicked()
{
QLineEdit* messageEdit = this->findChild<QLineEdit*>("messageEdit");
QString text = messageEdit->text();
if(text.length()>0)
{
QByteArray bytes = text.toUtf8();
std::string msg(bytes.data(),bytes.length());
_io->socket()->emit("new message",msg);//emit new message
text.append(":You");
QListWidgetItem *item = new QListWidgetItem(text);
item->setTextAlignment(Qt::AlignRight);
Q_EMIT RequestAddListItem(item);
messageEdit->clear();
}
}
```

## Further Reading

You can run the <a href="https://github.com/socketio/socket.io-client-cpp/tree/master/examples/QT/SioChatDemo">demo project</a> to get a closer look. Before you run it, please follow the <a href="https://github.com/socketio/socket.io-client-cpp#-with-cmake">instructions</a> to make the Socket.io client library.

Don't forget to <a href="https://github.com/socketio/socket.io-client-cpp">star the project</a> on GitHub to get updates!
]]>
<![CDATA[Socket.IO on iOS]]> https://socket.io/blog/socket-io-on-ios/ https://socket.io/blog/socket-io-on-ios/ Mon, 09 Mar 2015 00:00:00 GMT <![CDATA[We are pleased to announce the immediate availability of the Socket.IO Swift Client! Youll now be able to write code that runs natively on iOS and OSX, while maintaining the simplicity and expressiveness of the JavaScript client!]]> <![CDATA[

We are pleased to announce the immediate availability of the Socket.IO Swift Client! Youll now be able to write code that runs natively on iOS and OSX, while maintaining the simplicity and expressiveness of the JavaScript client!

import Foundation
let socket = SocketIOClient(socketURL: "localhost:8880")
socket.on("important message") {data, ack in
println("Message for you! \(data?[0])")
ack?("I got your message, and I'll send my response")
socket.emit("response", "Hello!")
}
socket.connect()

To show how you can use it in a real project, Ill show you how to create a small Tic Tac Toe app like the one shown above.

Overview

In this tutorial well look at creating a small iOS app that demonstrates socket.io and iOS. If you learn better from looking at code you can look at it here. The point of the tutorial is not to explain developing an iOS app, but to demonstrate how you can incorporate socket.io-client-swift into your projects! So it is assumed you have a basic knowledge of XCode. Note: This example uses Swift 1.2. However, 1.2 isnt much different from Swift 1.1, and the library has branches for Swift 1.1 and 1.2. The only difference in this guide is I use 1.2s expanded if let construct to avoid nesting. Note 2: While this library is written in, and meant for, Swift applications, it can be used with Objective-C projects, but will require some extra work (youll probably need to create a Swift class that can interface with your Objective-C code, as not all methods in the client will be available to Objective-C i.e emit, onAny). See this for more information.

Introduction

I designed socket.io-client-swift to be as close to socket.io-client as I could. So many of the ways you do things in socket.io-client look similar here! This is not a step-by-step tutorial for making a Tic Tac Toe app, only adding the socket.io-client part of it.

Setting up the Project

From Xcode, create a new project with the layout of single-view iOS application. You can name it whatever you like, Ill be naming mine TicTacIOiOS. The next step is getting the code for socket.io-client-swift, you can either use git to clone the repo to a directory, or simply download a release. Either way you get it, the process of adding it to your project is the same. Simply drag the folder named SwiftIO to the same place you copied SocketRocket! (Again making sure you select copy.) And thats it, the hardest part of putting our app together is done! At this point, if you want to test that its setup properly, try building and running the app, it should compile.

Adding Our Code

Now, assuming youve created your user interface. Its time to add the code that will interface with our socket.io server! In our demo application we have one UIViewController subclass, named ViewController. All of our code will be added there. First, we need to add a member named socket of type SocketIOClient to our ViewController.

let socket = SocketIOClient(socketURL: "localhost:8900")

Now, in our overridden viewDidLoad method we want to add two things, a method call that will add our handlers to our socket, and a call to connect our socket.

self.addHandlers()
self.socket.connect()

Handlers

Now that we have our method calls, its time to implement the method that adds the handlers!

func addHandlers() {
// Our socket handlers go here
}

Since were about to add the handlers, I think its worth mentioning the syntax I use for closures in Swift. Swift has many different ways of expressing closures, and they can be found here. But the form I use for adding handlers is a trailing closure, without explicit type annotations. You can use other closure forms if you wish. Im not going to show you all the handlers in our demo app here, just a few that demonstrate important things youll need to know when working with socket.io-client-swift. The first handler were going to add is one that will be called on any event, since its useful for debugging the API.

// Using a shorthand parameter name for closures
self.socket.onAny {println("Got event: \($0.event), with items: \($0.items)")}

The next handler that well add is the one that tells the app that the game has started.

self.socket.on("startGame") {[weak self] data, ack in
self?.handleStart()
return
}

Now to explain some things. [weak self] is a capture list. It tells the compiler that the reference to self in this closure should not add to the reference count of self. This is so when the socket object goes out of scope, the capture made in the closure doesnt keep it from being deallocated. The first parameter in all .on callbacks is an optional NSArray, it will contain all the data received with the event, or nil. The second parameter in the callback is an optional with the type of AckEmitter. AckEmitter is simply a typealias of (AnyObject...) -&gt; Void. Well see this used later. The next handler well add is the one for a win.

self.socket.on("win") {[weak self] data, ack in
if let name = data?[0] as? String, typeDict = data?[1] as? NSDictionary {
self?.handleWin(name, type: typeDict)
}
}

As mentioned before, this is new syntax for if let introduced in Swift 1.2. It simplifies optional unwrapping (pyramid of doom). The important thing to gather from this handler is that you do not need to force unwrap the array to get the object. Also note that a JSON object will be exposed to Swift as an NSDictionary. Another thing to note is that for almost all your handlers that have data, youll be doing some kind of optional unwrapping and type casting. This is an unfortunate consequence of working with JavaScript. The final handler that Ill demonstrate here is the one that handles whether the player wants to play again.

self.socket.on("gameReset") {data, ack in
ack?(false)
}

In this simplified example, we simply send an acknowledgement to the server that we dont ever want to play again. Remember that AckEmitter has a variadic definition, so you can send multiple things at once if you wanted.

Emitting Events

The next thing you'll probably want to know is how to send events from the client. Youll be pleased to know that it has a form almost exactly the same as socket.io-client! In our ViewController we have a method that handles when a user wants to make a move. Without going into the logic of that, well show how we send the data to the server.

@IBAction func btnClicked(btn:UIButton) {
let coord:(x:Int, y:Int)

// Long switch statement that determines what coord should be

self.socket.emit("playerMove", coord.x, coord.y)
}

Thats all you need to do for sending data! Some other examples of sending which arent covered in our demo are:

Sending JSON

As mentioned before, JSON in Swift is best represent as a Dictionary. Thankfully for you, you dont need to worry about turning it into something socket.io will understand, thats all done under-the-hood.

let myJSON = [
"name": "bob"
]

socket.emit("jsonTest", myJSON)

Sending Binary

Binary data is also handled by the client, so you dont need to worry about it.

let data = "Hello, ".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
let data2 = "World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

socket.emit("dataTest", data, ["world": data2])

Requesting Acks

The client can also request that the server send an ack for an event. This is done by using the emitWithAck method which returns an object to which you can add a handler.

socket.emitWithAck("needsAck", "test").onAck {data in
println("got ack with data: (data)")
}

A Note About Multitasking in iOS

As you probably know, iOS is very picky about what you can do in the background. As such, dont expect that your socket connection will survive in the background! Youll probably stop receiving events within seconds of the app going into the background. So its better to create a task that will gracefully close the connection when it enters the background (via AppDelegate), and then reconnect the socket when the app comes back into the foreground. If you want to learn more about the client, check out the README! We also invite you to contribute by submitting issues, patches, documentation and examples.

]]>
<![CDATA[Socket.IO 1.3.5]]> https://socket.io/blog/socket-io-1-3-5/ https://socket.io/blog/socket-io-1-3-5/ Tue, 03 Mar 2015 00:00:00 GMT <![CDATA[Socket.IO 1.3.5 addresses a parser issue. Upgrade recommended. Completely backwards-compatible.]]> <![CDATA[

Socket.IO 1.3.5 addresses a parser issue. Upgrade recommended. Completely backwards-compatible.

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.3.4]]> https://socket.io/blog/socket-io-1-3-4/ https://socket.io/blog/socket-io-1-3-4/ Sat, 14 Feb 2015 00:00:00 GMT <![CDATA[Socket.IO 1.3.4 corrects the 1.3.3 build that included extra unused code.]]> <![CDATA[

Socket.IO 1.3.4 corrects the 1.3.3 build that included extra unused code.

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.4/socket.io.min.js"></script>
]]>
<![CDATA[Socket.IO 1.3.3]]> https://socket.io/blog/socket-io-1-3-3/ https://socket.io/blog/socket-io-1-3-3/ Wed, 04 Feb 2015 00:00:00 GMT <![CDATA[Socket.IO 1.3.3 is a backwards-compatible recommended upgrade for everyone.]]> <![CDATA[

Socket.IO 1.3.3 is a backwards-compatible recommended upgrade for everyone.

  • It addresses a bug in the parser that could break the decoder with maliciously-crafted binary packets.

  • We now warn about errors in the console if you dont manually specify an error event handler for Socket objects on the server.

As usual, you can grab the latest client from the CDN!

<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.3/socket.io.min.js"></script>
]]>
<![CDATA[Native Socket.IO and Android]]> https://socket.io/blog/native-socket-io-and-android/ https://socket.io/blog/native-socket-io-and-android/ Tue, 20 Jan 2015 00:00:00 GMT <![CDATA[In this tutorial well learn how to create a chat client that communicates with a Socket.IO Node.JS chat server, with our native Android Client! If you want to jump straight to the code, it's on GitHub. Otherwise, read on!]]> <![CDATA[android chat demo

In this tutorial well learn how to create a chat client that communicates with a Socket.IO Node.JS chat server, with our native Android Client! If you want to jump straight to the code, it's on GitHub. Otherwise, read on!

Introduction

To follow along, start by cloning the repository: socket.io-android-chat.

The app has the following features:

  • Sending a message to all users joining to the room.
  • Notifies when each user joins or leaves.
  • Notifies when an user start typing a message.

Socket.IO provides an event-oriented API that works across all networks, devices and browsers. It's incredibly robust (works even behind corporate proxies!) and highly performant, which is very suitable for multiplayer games or realtime communication.

Installing the Dependencies

The first step is to install the Java Socket.IO client with Gradle.

For this app, we just add the dependency to build.gradle:

dependencies {
implementation ('io.socket:socket.io-client:2.0.0') {
exclude group: 'org.json', module: 'json'
}
}

We must remember adding the internet permission to AndroidManifest.xml.

<!-- app/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>

Now we can use Socket.IO on Android!

Using socket in Activity and Fragment

First, we have to initialize a new instance of Socket.IO as follows:

import io.socket.client.IO;
import io.socket.client.Socket;

private Socket mSocket;
{
try {
mSocket = IO.socket("http://chat.socket.io");
} catch (URISyntaxException e) {}
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSocket.connect();
}

IO.socket() returns a socket for http://chat.socket.io with the default options. Notice that the method caches the result, so you can always get a same Socket instance for an url from any Activity or Fragment. And we explicitly call connect() to establish the connection here (unlike the JavaScript client). In this app, we use onCreate lifecycle callback for that, but it actually depends on your application.

Emitting events

Sending data looks as follows. In this case, we send a string but you can do JSON data too with the org.json package, and even binary data is supported as well!

private EditText mInputMessageView;

private void attemptSend() {
String message = mInputMessageView.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
return;
}

mInputMessageView.setText("");
mSocket.emit("new message", message);
}

Listening on events

Like I mentioned earlier, Socket.IO is bidirectional, which means we can send events to the server, but also at any time during the communication the server can send events to us.

We then can make the socket listen an event on onCreate lifecycle callback.

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mSocket.on("new message", onNewMessage);
mSocket.connect();
}

With this we listen on the new message event to receive messages from other users.

import io.socket.emitter.Emitter;

private Emitter.Listener onNewMessage = new Emitter.Listener() {
@Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
JSONObject data = (JSONObject) args[0];
String username;
String message;
try {
username = data.getString("username");
message = data.getString("message");
} catch (JSONException e) {
return;
}

// add the message to view
addMessage(username, message);
}
});
}
};

This is what onNewMessage looks like. A listener is an instance of Emitter.Listener and must be implemented the call method. Youll notice that inside of call() is wrapped by Activity#runOnUiThread(), that is because the callback is always called on another thread from Android UI thread, thus we have to make sure that adding a message to view happens on the UI thread.

Managing Socket State

Since an Android Activity has its own lifecycle, we should carefully manage the state of the socket also to avoid problems like memory leaks. In this app, we’ll close the socket connection and remove all listeners on onDestroy callback of Activity.

@Override
public void onDestroy() {
super.onDestroy();

mSocket.disconnect();
mSocket.off("new message", onNewMessage);
}

Calling off() removes the listener of the new message event.

Further reading

If you want to explore more, I recommend you look into:

  • Other features of this app. They are just implemented with emit(), on() and off().

  • The documentation of the Java Socket.IO client

  • Many other great Socket.IO implementations created by the community!

]]>
<![CDATA[Introducing Socket.IO 1.0]]> https://socket.io/blog/introducing-socket-io-1-0/ https://socket.io/blog/introducing-socket-io-1-0/ Wed, 28 May 2014 00:00:00 GMT <![CDATA[The first version of Socket.IO was created shortly after Node.JS made its first appearance. I had been looking for a framework that easily enabled me to push data from a server to a client for a long time, and even had tried other approaches to server-side JavaScript.]]> <![CDATA[

The first version of Socket.IO was created shortly after Node.JS made its first appearance. I had been looking for a framework that easily enabled me to push data from a server to a client for a long time, and even had tried other approaches to server-side JavaScript.

At the time, the main focus was on an interface equivalent to the upcoming WebSocket API that was in the process of standardization. I was lucky to receive a lot of feedback from the community at the time (including Node.JS's creator) that helped shape the project into something significantly more useful.

Socket.IO has thus become the EventEmitter of the web. Today I want to talk about the work that has gone into 1.0 to round up this vision.

There's a lot to say about Socket.IO 1.0, so if you're short in time, feel free to jump to the parts that are most interesting to you:

  1. New engine
  2. Binary support
  3. Automated testing
  4. Scalability
  5. Integration
  6. Better debugging
  7. Streamlined APIs
  8. CDN delivery
  9. Future innovation
  10. Credits

New engine

The Socket.IO codebase no longer deals with transports and browser incompatibilities. That work has been relegated to a new module we've been perfecting for months called Engine.IO that implements a WebSocket-like API.

The benefits of this particular modularization can't be understated:

  • For the Socket.IO end user, nothing changes. Just drop-in the new version!
  • A tremendous simplification in terms of codebase size and testing surface
    • The Socket.IO Server is now only 1234 lines of code.
    • The Socket.IO Client is now only 976 lines of code.
  • Future-proof flexibility
    • If WebSocket is the only transport you want to support moving forward, Engine.IO (with all its browser hacks and workarounds) can be seamlessly removed.
    • Alternative transports such as vanilla Node.JS TCP Sockets or Google Chrome Sockets can be trivially implemented.

This separation has also allowed us to innovate and perfect the transport layer. One of my favorite improvements was introducing the idea of what I call transport feature detection.

Once upon a time in the web, it was extremely common to simply sniff User Agents to make decisions of what APIs to use or what behaviors to enable. As JavaScript codebases became more complex and mature, it became obvious that in order to maximize reliability, it made more sense to directly test the APIs to see if they would behave as expected.

For example, simply checking that the JSON global is present does not mean that JSON.stringify works, or even exists. It could have simply meant that the user defined a JSON global of their own, or the environment could have a broken JSON implementation.

Socket.IO never assumes that WebSocket will just work, because in practice there's a good chance that it won't. Instead, it establishes a connection with XHR or JSONP right away, and then attempts to upgrade the connection to WebSocket. Compared to the fallback method which relies on timeouts, this means that none of your users will have a degraded experience.

Binary support

Users have been asking for the ability to send binary data for a while, especially after WebSocket added support for it.

The main issue was that if we had modeled our binary support after the WebSocket API, its usefulness would have been fairly limited. WebSocket requires that you put your Socket either into string mode or binary mode:

var socket = new WebSocket('ws://localhost');
socket.binaryType = 'arraybuffer';
socket.send(new ArrayBuffer);

This is good for a low-level API, which is why Engine.IO now supports it, but application developers most likely don't want to send only blobs, or encode everything as a blob manually prior to sending it out.

Socket.IO now supports emitting Buffer (from Node.JS), Blob, ArrayBuffer and even File, as part of any datastructure:

var fs = require('fs');
var io = require('socket.io')(3000);
io.on('connection', function(socket){
fs.readFile('image.png', function(err, buf){
// it's possible to embed binary data
// within arbitrarily-complex objects
socket.emit('image', { image: true, buffer: buf });
});
});

To test how useful it would be to support binary in this particular way (and as a virtualization geek), I decided to replicate the Twitch Plays Pokemon experiment 100% in JavaScript. Using a JavaScript gameboy emulator, node-canvas, socket.io we came up with a server-rendered collaborative game that even works on IE8. Check it out on https://weplay.io (source code here).

The relevant code that sends the image data is:

self.canvas.toBuffer(function(err, buf){
if (err) throw err;
io.emit('frame', buf);
});

The next experiment was to run an instance of QEMU running an image of Windows XP, in honor of its retirement. Every player gets a 15 second turn to control the machine. Check out the demo on http://socket.computer. Here's a video of your typical inception scenario:

A key part of putting together this demo was connecting to the QEMU VNC server and implementing the RFB protocol. As it's usually the case with Node.JS, the solution was a npm search rfb away.

Essentially, in order to minimize latency and have the best performance, it's best to notify clients only of the pieces of the screen that changed. For example, if you move your mouse around, only little pieces of the screen that surround the cursor are broadcasted. The node-rfb2 module gives us a rect event with objects like the following:

{
x: 103,
y: 150,
width: 200,
height: 250,
data: Buffer
}

It then became clear to me that our support for binary data would be genuinely useful. All I had to do was call io.emit to pass that object around, and let Socket.IO do the rest.

Just for fun, I also installed and ran one of my favorite first person shooters:

Automated Testing

Every commit to the Socket.IO codebase now triggers a testing matrix totaling to 25 browsers, including Android and iOS.

We accomplish this by having make test seamlessly set up a reverse tunnel to ephemeral ports in your computer (thus making it accessible from the outside world), and have them execute on the Sauce Labs cloud, which is in charge of virtualizing and executing browsers on all the environments we care about.

Scalability

We simplified the approach towards rooms and multi-node scalability dramatically. Instead of storing and/or replicating data across nodes, Socket.IO is now only concerned with passing events around.

If you want to scale out Socket.IO to multiple nodes, it now comes down to two simple steps:

  • Turn on sticky load balancing (for example by origin IP address). This ensures that long-polling connections for example always route requests to the same node where buffers of messages could be stored.
  • Implement the socket.io-redis adapter.
var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

We have deprecated the Socket#set and Socket#get APIs. Packets now simply get encoded and distributed to other nodes whenever you broadcast, and we don't deal with storage.

This leads directly into our next goal: integration with other backends.

Integration

Chances are good that your existing application deployments are written in a variety of languages and frameworks, and are not just limited to Node.JS. Even if it was all Node.JS, you probably at some point want to separate concerns of your application into different processes.

One of the processes might be in charge of hosting the Socket.IO server, accepting connections, performing authentication, etc, and then another part of your backend might end up in charge of producing messages.

To that end we're introducing the socket.io-emitter project which hooks into socket.io-redis to easily allow you to emit events to browsers from anywhere:

var io = require('socket.io-emitter')();
setInterval(function(){
io.emit('time', new Date);
}, 5000);

Tony Kovanen already created a PHP implementation:

<?php
$emitter = new SocketIOEmitter(array('port' => '6379', 'host' => '127.0.0.1'));
$emitter->emit('event', 'wow');
?>

This makes it really easy to turn any existing application into a realtime application!

Better debugging

Socket.IO is now completely instrumented by a minimalistic yet tremendously powerful utility called debug by TJ Holowaychuk.

In the past, the Socket.IO server would default to logging everything out to the console. This turned out to be annoyingly verbose for many users (although extremely useful for others), and violates the Rule of Silence of the Unix Philosophy:

**Rule of Silence**
Developers should design programs so that they do not print unnecessary output. This rule aims to allow other programs and developers to pick out the information they need from a program's output without having to parse verbosity.
The basic idea is that each module used by Socket.IO provides different debugging scopes that give you insight into the internals. By default, all output is suppressed, and you can opt into seeing messages by supplying the `DEBUG` env variable (Node.JS) or the `localStorage.debug` property (Browsers).

You can see it in action for example on our homepage:

Streamlined APIs

The socket.io module now exports the attachment function directly (previously .listen).
It's even easier now to attach socket.io to a HTTP server:

var srv = require('http').Server();
var io = require('socket.io')(srv);

or to make it listen on some port:

var io = require('socket.io')(8080);

Before, to refer to everyone connected you had to use io.sockets. Now you can call directly on io:

io.on('connection', function(socket){
socket.emit('hi');
});
io.emit('hi everyone');

CDN delivery

One of the best decisions we made early on was that implementing a Socket.IO server would not only give you access to the realtime protocol, but Socket.IO itself would also serve the client.

Normally, all you have to do is to include a snippet like this:

<script src="/socket.io/socket.io.js"></script>

If you want to optimize access to the client by serving it near your users, provide the maximum level of gzip compression (thanks to Google's zopfli and proper support for caching, you can now use our CDN. It's free, forever, and has built-in SSL support:

<script src="https://cdn.socket.io/socket.io-1.0.0.js"></script>

Future innovation

The core Socket.IO projects will continue to improve with lots of more frequent releases, with the sole goal of improving reliability, speed and making the codebase smaller and easier to maintain. Socket.IO 2.0 will probably see us ditching support for some older browsers, and not bundling some modules like the JSON serializer.

Most of the innovation in the Socket.IO world will happen outside of the core codebases. The most important projects that I'll be closely watching are the following:

socket.io-stream

By adding this plugin, you'll be able to send Stream objects so that you can write memory-efficient programs. In the first example we loaded a file into memory prior to emitting it, but the following should be possible:

var fs = require('fs');
var io = require('socket.io')(3000);
require('socket.io-stream')(io);
io.on('connection', function(socket){
io.emit(fs.createReadStream('file.jpg'));
});

And on the client side you'll receive a Stream object that emits data events.

Tooling

When you use Socket.IO you don't care about transports, packets, frames, TCP or WebSocket. You care about what events are sent back and forth.

Our goal is to have plugins for Web Inspector, Firefox Developer Tools that allow you to easily introspect what events are being sent, when, and what their parameters are.

This project is being led by the talented Nick LaGrow (Github), Samaan Ghani (Github) and David Cummings (Twitter).

New languages and frameworks

A lot of effort has gone into specing and documenting the Engine.IO protocol and Socket.IO protocol.

The main goal behind this is that the Node.JS servers and clients become the reference implementations for many other languages and frameworks. Interoperability within the larger ecosystem is one of our biggest goals for 2014 and beyond.

Credits

This release has been a big team effort. Special thanks go out to our new core team:

  • Tony Kovanen (Github / Twitter) for his amazing work on Engine.IO binary support and research into a variety of workarounds to support all versions of iOS and Internet Explorer, his help in putting together this website and rounding up the docs.

  • Kevin Roark (Github) for the entire development of the new Socket.IO parser on top of Engine, the Socket.IO Computer demo, and help with docs, issues and pull requests.

  • Roman Shtylman (Github / Twitter) for his work on zuul and localtunnel, crucial to our testing architecture and our mission of reliability.

And in no particular order:

  • Jay Borenstein (LinkedIn) for selecting Socket.IO as one of the projects to mentor students on Open Source engineering as part of the Open Academy project.

  • Michael Srb (Github), Mark Mokryn (Github), Eugen Dueck (Github), Afshin Mehrabani (Github), Christoph Dorn (Github) and Mikito Takada (Github) for several key Engine.IO patches.

  • Grant Timmerman (Github / Twitter) for his outstanding work on the new Socket.IO example chat application, and multiple patches and issues investigation.

  • Jxck (Github / Twitter) for his work on translation, documentations and patches. ありがとう

  • Arnout Kazemier (Github / Twitter) for his multiple contributions to Engine.IO and Socket.IO

  • Sauce Labs (Github / Twitter) for supporting open source projects with free testing infrastructure.

  • Shihui Song (Github), Qiming Fang (Github) and Erluo Li for their work on testing infrastructure.

  • Julian Salazar (Github) and Tianyiu Liu (Github) for their work on reconnection and ongoing research into resource sharing between browser tabs and messages synchronization.

  • Gal Koren (Github) for his fantastic work into modularization of the codebases.

  • Matt Walker (Twitter) for the beautiful Socket.IO logo.

Finally, I'm very grateful to my company Automattic for being a great home to Open Source innovation.

]]>