Getting Started With Node SocketIO
WebSocket
What are websockets?
- Communication between a client(browser) and server
- Bidirectional (data flows both ways)
- Allows real-time data flow
Allows real time communication such as chat rooms between multiple clients.
Applications for websocket?
- Multiple browser games
- Chat rooms
- Colloborative code editing
- Live text for sports/news website
- Online drawing canvas
- Real-Time to-do apps with multi users
Dependencies:
- Node
- Express
- socket.io
Client and server side code
socket.io requires both client and server side code for them to communicate.
Below is a server side code
const express = require('express')
const socketio = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = socketio(server)
const port = process.env.PORT || 3000
let count = 0
// Whenever a new connection gets fired, io.on('connection'..) gets executed.
io.on('connection',(socket) => {
console.log("New WebSocket Connection.")
/*
Send data to a particular connection. Since a new client
was connected, we don't need to send current count to all connections. Just to the one that is recently connected.
*/
socket.emit('countUpdated', count)
socket.on('increment', () => {
count++
/*
socket.emit() : will emit to a particular connection
io.emit(): will emit to all the connections that's avaliable
*/
io.emit('countUpdated',count)
})
})
server.listen(port, () =>{
console.log(`Server is up on port ${port}`)
})
Client Code
index.html
<script src="/socket.io/socket.io.js"></script>
<script src="/js/chat.js"></script>
<button id="increment"> +1 </button>
chat.js
// This will connect to our server
const socket = io()
socket.on('countUpdated', (count)=>{
console.log('The count has been updated', count)
})
document.querySelector('#increment').addEventListener('click', () => {
console.log('clicked')
socket.emit('increment')
})
Commonly used methods
Receive Data
- socket.on(eventName, callback)
socket.on(), is used to receive data
Parameters:
- eventName (String)
- callback (Function)
- Returns Socket
Register a new handler for the given event. Used more to receive data.
socket.on('news', (data) => {
console.log(data);
});
// with several arguments
socket.on('news', (arg1, arg2, arg3) => {
// ...
});
// or with acknowledgement
socket.on('news', (data, callback) => {
callback(0);
});
Send Data to a Connection
- socket.emit(eventName[, …args][, ack])
socket.emit(), is used to send data to a particular connection
Parameters:
- eventName (String)
- args
- ack (Function)
- Returns Socket
Emits (dends) an event to the socket identified by the string name. Any other parameters can be included. All serializable datastructures are supported, including Buffer.
The ack argument is optional and will be called with the server answer.
Used to send data
const socketio = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = socketio(server)
io.on('connection',(socket) => {
socket.emit('event','message')
})
Send data to call connections
Send data to all connections including the socket that starts it.
const socketio = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = socketio(server)
io.on('connection',(socket) => {
io.emit('event','message')
})
Broadcast Data
Broadcasting means sending a message to everyone else except for the socket that starts it. More Info
- socket.broadcast.emit(eventName, data)
const socketio = require('socket.io')
const app = express()
const server = http.createServer(app)
const io = socketio(server)
io.on('connection',(socket) => {
console.log("New WebSocket Connection.")
socket.broadcast.emit('message', 'A new user has joined!')
})
Detect if a socket (client) is closed
Inorder to detect a client has left a connection or also knows as if a socket is closed.
- socket.on(‘disconnect’,callback) ``` js const socketio = require(‘socket.io’) const app = express() const server = http.createServer(app) const io = socketio(server)
io.on(‘connection’,(socket) => { socket.on(‘disconnect’,() => { io.emit(‘message’,’A user has left!’) }) })
## Data Acknowledgements
When we send data from client to server or vice-versa, we can also choose to have an ack, stating we have received the data.
**Client**
``` js
const socket = io()
socket.emit('sendMessage', message, (ack) => {
console.log('The message was delivered!', ack)
})
Server
io.on('connection',(socket) => {
socket.on('sendMessage', (message, callback) => {
// Send received message to all users
io.emit('message',message)
// What we want to send back as ack
callback('Delivered')
})
}
Socket Unique ID
A unique identifier for the session, that comes from the underlying Client.
io.on('connection',(socket) => {
console.log(socket.id)
}
Namespaces
Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths.
This is a useful feature to minimize the number of resources (TCP connections) and at the same time separate concerns within your application by introducing separation between communication channels.
Important note: The namespace is an implementation detail of the Socket.IO protocol, and is not related to the actual URL of the underlying transport, which defaults to /socket.io/….
For More Info About Namespaces and Rooms
Rooms
Within each namespace, you can also define arbitrary channels that sockets can join and leave.
Joining and leaving
You can call join to subscribe the socket to a given channel:
io.on('connection', function(socket){
socket.join('some room');
});
And then simply use to or in (they are the same) when broadcasting or emitting:
io.to('some room').emit('some event');
To leave a channel you call leave in the same fashion as join. Both methods are asynchronous and accept a callback argument.
Emit and Broadcast Data in a Room
- io.to.emit(): Send data to everyone in a specific room ``` js
* socket.broadcast.to.emit:
Send data to everyone in a specific room except the one sending it.
``` js
socket.broadcast.to(room).emit('message', 'data to send')
Default room
Each Socket in Socket.IO is identified by a random, unguessable, unique identifier Socket#id. For your convenience, each socket automatically joins a room identified by its own id.
This makes it easy to broadcast messages to other sockets:
io.on('connection', function(socket){
socket.on('say to someone', function(id, msg){
socket.broadcast.to(id).emit('my message', msg);
});
});
Disconnection
Upon disconnection, sockets leave all the channels they were part of automatically, and no special teardown is needed on your part.