<style>
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap');
.reveal {
font-family: "Roboto Mono", monospace;
font-size: 40px;
}
</style>
# Socket.IO Overview
---
## What is Socket.IO?
* Used for real-time applications (need to see changes immediately, without having to refresh the page)
* Examples
* Instant messenger
* Push notifications
* Collab apps (Google Drive, etc.)
* Online Gaming
----
* Uses open connections between the client and server to facilitate realtime communication
* Allows bi-directional communication
* TLDR; whenever an event occurs (like a client sends a new message), the server will receive the event and push it to the connected clients (no refreshes!)
---
## How Socket.IO works
* Emits information from one client to the server, then the server emits that information to the rest of the clients
* All clients can emit events to the server
---
## Example: Chat app
* With sockets, when the server receives a new message, it will send it to the client and notify them about the changes
* DON'T need to send requests between the client and server
----
## How would this work without Socket.IO?
* Client 1 would send a POST request to add a new message to the database
* Client 1 - 3 would need to then send a GET request to get the new array of messages from the database (usually by reloading)
* This is not how chat apps should work!!
---
## Installations
* Express: ```npm i express```
* Server Socket.IO: ```npm i socket.io```
* Client Socket.IO: ```npm i socket.io-client```
----
## Setting up Socket.IO on the server
We will set up Socket.IO in our main server file (index.js)
```javascript=
const app = require("express")();
const server = app.listen(5000, () => console.log("listening on port 5000"))
const io = require("socket.io")(server);
/*
* listens for a connection event and runs the function after
* connection event auto emitted when bi-directional connection
* io.on event handler handles connection, disconnection events in it
* Each specific socket is a channel between a client and server, a.k.a.
* each client has its own socket
*/
io.on("connection", function(socket){
// user entering page causes "connection" event to emit
console.log("user connected");
// when someone leaves page, the disconnect event is emitted
socket.on('disconnect', function(){
console.log("a user disconnected")
})
})
```
----
Whenever a user goes onto our page, "user connected" will be logged, and whenever the user closes the page, "a user disconnected" will be logged.
----
## Setting up Socket.IO on the client
Inside of a React component, add the following
```javascript=
import socketIOClient from "socket.io-client";
import React, {Component} from 'react';
class App extends Component {
constructor() {
super();
this.state = {
// same as server, which the socket is listening on
endpoint: "http://localhost:5000"
};
}
componentDidMount() {
const { endpoint } = this.state;
// create a new client socket with the given endpoint
const socket = socketIOClient(endpoint);
// wait for a "someEvent" event to emit, then run the function
socket.on("someEvent", eventData => console.log(eventData));
}
render(){
...
}
}
```
----
The server may emit a "someEvent" event, and when that emits, this client will run the provided function.
----
## Emit an event from the client and receive on the server
```javascript=
// inside client
const socket = socketIOClient(endpoint);
socket.emit('clientEvent', {/* some data */});
```
``` javascript=
//inside server
io.on('connection', socket => {
// when a client emits clientEvent, will do something with the sent data
socket.on('clientEvent', data => {
// do something with the data
})
})
```
----
It works the same if you emitted an event from the server and listened for it in the client
----
## Broadcasting events
**Broadcasting**: send a message to all connected clients, clients on a namespace, or clients in a particular room
----
## Broadcast to all connected clients
```javascript=
/*
* In index.js
*/
// on the server, so this counter won't reset until server ends
var numClients = 0;
io.on("connection", socket => {
// keep track of number of users that have connected
numClients++;
io.sockets.emit("broadcast", {text:`${numClients} clients connected`})
})
```
----
```javascript=
/*
* In the client
*/
var socket = socketIOClient(endpoint);
socket.on("broadcast", data => {
console.log(data);
})
```
---
## Example: Setting up a chat room!
* We would have multiple clients (whoever is apart of the chat room)
* Any client can have data (the message that the user typed) and can send that data to the server when the user sends the message
* Server receives data and emit it down every other WebSocket to every other client
* The clients in the frontend would display the new message
----
## What would happen in the frontend?
* When the send button is clicked, get the text that was typed (stored in state!) and use it to emit a "message" event with the text as data
```javascript=
socket.emit("message", {message: this.state.message});
```
----
## How would the server handle the "message" event?
* Inside of ```io.on("connection", socket => {...})```, we want to have an event listener to listen for the "message" event
```javascript=
// this socket refers to the specific socket connecting the server and the client sending the message
socket.on("message", data => {
// do something with data
})
```
----
## What do we want to do with the new message on the server?
We want to send it out to all clients connected to the server!
----
```javascript=
socket.on("message", data => {
// io.sockets refers to all sockets connected to server
// got the data from a specific client, now emit that message to all clients
io.sockets.emit("message", data);
})
```
----
Now in the frontend, we want to receive this "message" event, since this message event will be carrying the new message that one of the client's just sent!
----
```javascript=
// inside of the frontend, listen for the message event
socket.on("message", data => {
// append new message to state's message array
this.setState(prevState => {
const messageList = prevState.messageList.push(data.message);
// return the new state to update the state
return {messageList}
})
})
```
{"metaMigratedAt":"2023-06-15T04:11:12.744Z","metaMigratedFrom":"Content","title":"Socket.IO Overview","breaks":true,"contributors":"[{\"id\":\"0ffe3cdf-ee91-4b9a-9e67-32d09c41aec9\",\"add\":21,\"del\":1},{\"id\":\"25be75a2-9a21-4137-a70a-c55f361a5189\",\"add\":7607,\"del\":1079}]"}