👓💻 How to set up Websocket connections between nodejs services
Tags: node, webdev, javascript, beginners
Published: 2020-05-03 17:24:54

Most of the tutorials and lessons on the internet are about how to connect your browser with a server via WebSockets. In this blog post, I want to show you that you can also use WebSockets to connect servers with each other and on the way also explain it a little bit.

## What are WebSockets?

`WebSockets` are a bi-directional connection and a communications protocol initiated over HTTP.

This means that both the server and the client can send and react to a message and talk to each other without creating a new connection since WebSockets are always stay connected.

Websockets need an HTTP connection to tell both that you want to upgrade to WebSockets. The connection then will be upgraded to WebSockets. You can see this because all the WebSocket connection have a `ws://` instead of an `http://` in the URL.

Websocket connections also support a secure connection which you should use in production. You can see this like in HTTP you just need to add an `s`. `http` would be `https` and `ws` would be `wss`. You should also not mix secure with insecure connections. In general, always secure everything.

What we will do in this small tutorial is to connect three services with each other and send a message between them. We will also add colourful logging to make it easier to read the logs. We will also use nodemon for easier development.

## The Setup

Let us first create our project.

```bash
mkdir websockets-tutorial
cd websockets-tutorial
npm init -y
git init
```

Now, let us add the packages we will be using and create the files we need.
```bash
npm i -s chalk nodemon socket.io socket.io-client
touch service1.js service2.js service3.js
```
The next step is to create our npm scripts.
Open your `package.json` and add the following scripts:
```js
  "scripts": {
    "start": "npm run service1 & npm run service2 & npm run service3",
    "service1": "nodemon service1.js",
    "service2": "nodemon service2.js",
    "service3": "nodemon service3.js"
  },
```
## The implimantion

Let us first write a log function that will output colourful logs.
We need to import `chalk` first.
```js
const chalk = require('chalk');
```
and then we can implement a simple `log` function.

```js
const log = (msg) => console.log(chalk.bold.green.bgBlack('Service1:'), chalk.white.bgBlack(`${msg}`))
```
We will use the same function in every file and we need to change a few things. The following part of the code needs to be changed in the place where I have added `[ ]` around it.
```js
chalk.bold.[green].bgBlack('Service[1]:')
```
`[green]` I would take another colour for every service and of course the `[1]` needs to be changed to the number.

#### The WebSocket server

First let us import the packages we need.

```js
const server = require('http').createServer();
const io = require('socket.io')(server, {
    path: '/'
});
```

Here we are importing the `http` server from node and passing it to `socket.io`.
In `socket.io` we need to set the path the server should listen to for incoming connections. In our case, it is the root path `/`.

At the end of your file, add the following code to make the server listen to a port.
```js
server.listen(4000);
log('started server on port 4000')
```
In service1 the port will be 4000 and in service2 it will be port 5000 and in service3 it will be the port 6000.

Okay now, let us implement the actual communication.
```js
io.on('connection', client => {
    log('someone connected');

    client.on('sayHello', data => {
        log(`event: sayHello, data: ${data}`)
        client.emit('halloToYouTo', 'Hello from http://localhost:4000')
    });

    client.on('disconnect', () => {
        log('client disconnected')
    });
});
```
Okay, we are dealing with WebSockets. Websockets are always connected so we need to react to things happening. This is why you will see `.on()` and `.emit()`.
`.on()` shows you that the function will run when something will happen.
For example: `io.on('connection', someFunction);`. You can translate in your head to: "When someone connected to our WebSocket the `someFunction` will be run".
Inside of that we have the following code `client.on('sayHello', sayHelloFunction)`. The `sayHelloFunction` will be executed once a client has emitted the 'SayHello' event. We then `.emit()` the 'HalloToYouTo' event. This will be then sent to all open connections. Then you should already understand what `disconnect` will do, right?

Here is the full code of the `service`.js file
```js
const chalk = require('chalk');
const server = require('http').createServer();
const io = require('socket.io')(server, {
    path: '/'
});

const log = (msg) => console.log(chalk.bold.green.bgBlack('Service1:'), chalk.white.bgBlack(`${msg}`))

io.on('connection', client => {
    log('someone connected');

    client.on('sayHello', data => {
        log(`event: sayHello, data: ${data}`)
        client.emit('halloToYouTo', 'Hello from http://localhost:4000')
    });

    client.on('disconnect', () => {
        log('client disconnected')
    });
});

server.listen(4000);
log('started server on port 4000')
```

Lets now go to implement `servie2.js`.
```js
const chalk = require('chalk')
const server = require('http').createServer();
const ioServer = require('socket.io')(server, {
    path: '/'
});
const ioClient = require('socket.io-client');

const log = (msg) => console.log(chalk.bold.cyan.bgBlack('Service2:'), chalk.white.bgBlack(`${msg}`))
```

So until here, the code looks like in `service1.js`. The only change is that we are importing now the `socket.io-client` as `ioClient`.

Next we will setup a server again
```js
// Server Code
ioServer.on('connection', client => {
    log('someone connected');
    client.on('sayHello', data => {
        log(`event: sayHello, data: ${data}`)
        client.emit('halloToYouTo', "hello from http://localhost:5000")
    });
    client.on('disconnect', () => {
        log('event: disconnect, client disconnected')
    });
});
```
This is the same code as in `service1.js`.
Now let's implement the client. First we need to initalize the client.
```js
// Client Code
const serverAddr = 'http://localhost:4000';
const socket = ioClient(serverAddr, {
    path: '/'
});
```

The `serverAddr` must be the address of the server we want to connect. In our case, this is `service1` with the address `http://localhost:4000`. Remember we need HTTP to connect, but after the first handshake, the connection will be upgraded to a WebSocket connection. Now that we have that setup, we can now connect and set up the events we want to react to.
```js
socket.on('connect', (data) => {
    log(`connected to ${serverAddr}`);

    socket.emit('sayHello', 'Hello World from client');

    socket.on('halloToYouTo', data => {
        log(`event: helloToYouTo, ${data}`)
    });
});
```

As you can see, this almost looks the same as the server. We have our `.emit()` and `.on()`. So when we are connected to the server, then we will `.emit()` the `sayHello` event and if we look back at `service1.js` then we will see that it is listening to that event and it will emit the `helloToYouTo` event. So we send a message to `service1.js` and got a message back. Easy, right?

Okay here is the full `service2.js`
```js
const chalk = require('chalk')
const server = require('http').createServer();
const ioServer = require('socket.io')(server, {
    path: '/'
});
const ioClient = require('socket.io-client');

const log = (msg) => console.log(chalk.bold.cyan.bgBlack('Service2:'), chalk.white.bgBlack(`${msg}`))

// Server Code
ioServer.on('connection', client => {
    log('someone connected');
    client.on('sayHello', data => {
        log(`event: sayHello, data: ${data}`)
        client.emit('halloToYouTo', "hello from http://localhost:5000")
    });
    client.on('disconnect', () => {
        log('event: disconnect, client disconnected')
    });
});

// Client Code
const serverAddr = 'http://localhost:4000';
const socket = ioClient(serverAddr, {
    path: '/'
});
socket.on('connect', (data) => {
    log(`connected to ${serverAddr}`);

    socket.emit('sayHello', 'Hello World from client');

    socket.on('halloToYouTo', data => {
        log(`event: helloToYouTo, ${data}`);
    });
});

server.listen(5000);
log('started server on port 5000');
```

Now we know how to connect two services!
In the repository, you will see three services!
Let us do something different! Instead of me explaining the implementation. I will show you the file and you down in the comments can try to explain how it works!
So here is the `service3.js`
```js
const chalk = require('chalk')
const ioClient = require('socket.io-client');

const log = (msg) => console.log(chalk.bold.magenta.bgBlack('Service3:'), chalk.white.bgBlack(`${msg}`));

// Client Code
const clientAddr = 'http://localhost:5000';
const socket = ioClient(clientAddr, {
    path: '/'
});

socket.on('connect', (data) => {
    log(`connected to ${clientAddr}`);
    socket.emit('sayHello', 'Hello World from client');

    socket.on('halloToYouTo', data => {
        log(`event: halloToYouTo, data: ${data}`);
    });
});
log('started client ready');
```

This is how your output should look:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/slgw94i8g26guf1lu14b.png)

And you can find the repo [here](https://github.com/lampewebdev/websockets-tutorial)

**👋Say Hello!** [Instagram](https://www.instagram.com/lampewebdev/) | [Twitter](https://twitter.com/lampewebdev) | [LinkedIn](https://www.linkedin.com/in/michael-lazarski-25725a87) | [Medium](https://medium.com/@lampewebdevelopment) | [Twitch](https://dev.to/twitch_live_streams/lampewebdev) | [YouTube](https://www.youtube.com/channel/UCYCe4Cnracnq91J0CgoyKAQ)