├── .eslintignore ├── .eslintrc.json ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── assets ├── banner.jpg └── youtube.svg ├── package.json └── src ├── config └── connection.js ├── first-demo ├── client-receiver.js └── server-emitter.js └── second-demo ├── client-emitter.js ├── client-receiver.js └── server-dispatcher.js /.eslintignore: -------------------------------------------------------------------------------- 1 | env 2 | node_modules 3 | **/assets 4 | empty -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "airbnb-base" 8 | ], 9 | "globals": { 10 | "Atomics": "readonly", 11 | "SharedArrayBuffer": "readonly" 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 2018, 15 | "sourceType": "module" 16 | }, 17 | "rules": { 18 | } 19 | } -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [JoseJPR] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2020 @JoseJPR 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
With this tutorial you can create Net Communication client-client and server-clients with Nodejs.
8 | 9 | 22 | 23 | ## 🔖 Description 24 | 25 | The net module provides an asynchronous network API for creating stream-based TCP or IPC servers (net.createServer()) and clients (net.createConnection()). 26 | 27 | With this Tutorial you can create a Nodejs Net Server and communicate with severals Clients via Socket. 28 | 29 | Official Documentation: [NodeJS | API Net](https://nodejs.org/api/net.html) 30 | 31 | ## 📹 Video Demo 32 | 33 | How to execute a Net Server and two Clients and how the Server send random message to all Clients. 34 | 35 | [](https://youtu.be/AQiL8hWZeEg) 36 | 37 | How to Execute a Net Server and two Clients and how a Client send random message via Server to others Clients. 38 | 39 | [](https://youtu.be/Sfx0kYMzf78) 40 | 41 | ## ⛅️ Develop in the Cloud 42 | 43 | You can run this project in Gitpod, a one-click online IDE for GitHub: 44 | 45 | [](https://gitpod.io/#https://github.com/JoseJPR/tutorial-nodejs-net-socket-server-clients) 46 | 47 | ## 📌 Methodologies and Guidelines 48 | 49 | List of methodologies and tools used in this project for compliance with Quality Assurance Code (QAC) 50 | 51 | * ESTlint, tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. \ 52 | [NPM ESLint](https://www.npmjs.com/package/eslint) \ 53 | [NPM ESLint | Airbnb](https://www.npmjs.com/package/eslint-config-airbnb) 54 | 55 | ## ✅ Prerequisites 56 | 57 | In order to work with this project, your local environment must have at least the following versions: 58 | 59 | * Nodejs Version: 13.xx 60 | * NPM Version: 6.12.0 61 | 62 | ## 📐 How to work with this project 63 | 64 | You have to do the following steps to be able to work with this project. 65 | 66 | ### 1️⃣ Install Nodejs Dependencies 67 | To work with this project locally it is necessary to install the NPM dependencies. 68 | 69 | ```bash 70 | # Install npm dependencies 71 | $npm i 72 | ``` 73 | 74 | ### 2️⃣ Run 75 | 76 | You will find two demos, in the first one, the server emit messages from a "setInterval" function to all the clients subscribed by socket and in the second one a client emit with a "setInterval" function severals message to the server by socket and this is transmitted to the other clients. 77 | 78 | #### To run the first demo you need to activate at least ONE Server type Emitter and ONE Client Receiver: 79 | 80 | ```bash 81 | # Run Server for Emit Messages 82 | $npm run start:first-demo:server-emitter 83 | 84 | # Run Client for Receive Message 85 | $npm run start:first-demo:client-receiver 86 | ``` 87 | 88 | #### To run the second demo you need to activate ONE Server Dispatcher, at least ONE Clients Emitter and Others Receivers: 89 | 90 | ```bash 91 | # Run Server for Receive and Emit Messages 92 | $npm run start:second-demo:server-dispatcher 93 | 94 | # Run Client for Emit Messages 95 | $npm run start:second-demo:client-emitter 96 | 97 | # Run at least one Client for Receive Messages 98 | $npm run start:second-demo:client-receiver 99 | ``` 100 | 101 | ## 📂 Code scaffolding 102 | 103 | ```any 104 | / 105 | ├── assets 🌈 # Images Sources. 106 | ├── src 📦 # Main App with Server and Client. 107 | | ├── first-demo # Demo with broadcast demo server sending randoms message to all clients. 108 | | ├── second-demo # Demo with a client sending random message via server to all other clients. 109 | | └── ... 110 | └── ... 111 | ``` 112 | 113 | ## ⛽️ Review and Update Dependences 114 | 115 | For review and update all npm dependences of this project you need install in global npm package "npm-check-updates" npm module. 116 | 117 | ```bash 118 | # Install and Run 119 | $npm i -g npm-check-updates 120 | $ncu 121 | ``` 122 | 123 | ## License 124 | 125 | [MIT](LICENSE.md) 126 | 127 | ## Happy Code 128 | 129 | Created with JavaScript, lot of ❤️ and a few ☕️ 130 | 131 | ## This README.md file has been written keeping in mind 132 | 133 | - [GitHub Markdown](https://guides.github.com/features/mastering-markdown/) 134 | - [Emoji Cheat Sheet](https://www.webfx.com/tools/emoji-cheat-sheet/) 135 | -------------------------------------------------------------------------------- /assets/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoseJPR/tutorial-nodejs-net-socket-server-clients/62aac7514d15050104fcad170242560cb48fed8d/assets/banner.jpg -------------------------------------------------------------------------------- /assets/youtube.svg: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorial-nodejs-net-socket-server-clients", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "scripts": { 7 | "start:first-demo:server-emitter": "node ./src/first-demo/server-emitter.js", 8 | "start:first-demo:client-receiver": "node ./src/first-demo/client-receiver.js", 9 | "start:second-demo:server-dispatcher": "node ./src/second-demo/server-dispatcher.js", 10 | "start:second-demo:client-emitter": "node ./src/second-demo/client-emitter.js", 11 | "start:second-demo:client-receiver": "node ./src/second-demo/client-receiver.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/JoseJPR/tutorial-nodejs-net-socket-server-clients.git" 16 | }, 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/JoseJPR/tutorial-nodejs-net-socket-server-clients/issues" 21 | }, 22 | "homepage": "https://github.com/JoseJPR/tutorial-nodejs-net-socket-server-clients#readme", 23 | "dependencies": { 24 | "pino": "^5.16.0", 25 | "pino-pretty": "^3.6.0" 26 | }, 27 | "devDependencies": { 28 | "eslint": "^6.8.0", 29 | "eslint-config-airbnb-base": "^14.0.0", 30 | "eslint-plugin-import": "^2.20.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/config/connection.js: -------------------------------------------------------------------------------- 1 | const connection = { 2 | HOST: '127.0.0.1', 3 | PORT: '8124', 4 | }; 5 | 6 | export default connection; 7 | -------------------------------------------------------------------------------- /src/first-demo/client-receiver.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Client A Net Connection with Server with emit severals message second by second Without Close Socket. 3 | */ 4 | 5 | /** Require generics dependences */ 6 | import net from 'net'; 7 | import pino from 'pino'; 8 | import connection from '../config/connection.js'; 9 | 10 | // Set pino for get pretty logs. 11 | const logger = pino({ 12 | prettyPrint: { colorize: true } 13 | }) 14 | 15 | const client = net.createConnection({ 16 | host: connection.HOST, 17 | port: connection.PORT, 18 | }, () => { 19 | logger.info('Connected with server!'); 20 | }); 21 | 22 | client.on('connect', () => { 23 | logger.info('Client connected'); 24 | }); 25 | 26 | client.on('ready', () => { 27 | logger.info('Client ready'); 28 | }); 29 | 30 | client.on('data', (data) => { 31 | // Clear terminal. 32 | process.stdout.write('\x1b[2J'); 33 | // Show message from server. 34 | logger.info(data.toString()); 35 | }); 36 | 37 | client.on('end', () => { 38 | console.log('Disconnected from server'); 39 | }); -------------------------------------------------------------------------------- /src/first-demo/server-emitter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Create Net Server and two clients and send Message to differents client Pear to Pear. 3 | */ 4 | 5 | /** Require generics dependences */ 6 | import net from 'net'; 7 | import pino from 'pino'; 8 | import connection from '../config/connection.js'; 9 | 10 | // Set pino for get pretty logs. 11 | const logger = pino({ 12 | prettyPrint: { colorize: true } 13 | }) 14 | 15 | // Define main variables. 16 | let server; 17 | const clients = []; 18 | 19 | // Function to show clients number connected. 20 | const showClientsConnected = () => { 21 | server.getConnections((err, count) => { 22 | if (err) throw err; 23 | logger.info(`Connections Number: ${count} and Clients registerd in array: ${clients.length}`); 24 | }); 25 | }; 26 | 27 | // Function to register client into array clients for set an id. 28 | const registerClient = (id, socket) => { 29 | const _socket = socket; 30 | _socket.id = id; 31 | 32 | // Add into clients array a new client reference. 33 | clients.push(_socket); 34 | 35 | // Send message to client with custom id. 36 | _socket.write(`Your Client Id is: ${id}`); 37 | 38 | _socket.on('end', () => { 39 | logger.warn(`Client disconnected with id: ${_socket.id}`); 40 | // Get index position of client into array by id. 41 | const index = clients.findIndex((e) => e.id === _socket.id); 42 | // Remove client from array by index. 43 | clients.splice(index, 1); 44 | 45 | // Show Clients number connected. 46 | showClientsConnected(); 47 | }); 48 | _socket.pipe(_socket); 49 | }; 50 | 51 | // Create Server Net. 52 | server = net.createServer((socket) => { 53 | // Connection Listener. 54 | logger.warn('Client connected'); 55 | 56 | // Show Clients number connected. 57 | showClientsConnected(); 58 | 59 | // Register client into array for send message to a client. 60 | registerClient(Date.now(), socket); 61 | }); 62 | 63 | server.on('error', (err) => { 64 | logger.error(err); 65 | }); 66 | 67 | // Define host and port of server. 68 | server.listen({ 69 | host: connection.HOST, 70 | port: connection.PORT, 71 | }, () => { 72 | // Get and show info of server. 73 | const info = server.address(); 74 | logger.info(`Server Net actived on: ${info.address} and port: ${info.port}`); 75 | }); 76 | 77 | // Interval to get clients from array to send random a message pear to pear client. 78 | setInterval(() => { 79 | // Send messages to clients if has as minimum of two registered. 80 | if (clients.length > 0) { 81 | // Get random client from array. 82 | const client = clients[Math.round(Math.random()*(clients.length-1))]; 83 | // Write message to client. 84 | client.write(`Hi Client: ${client.id}, this is a timestamp: ${Date.now()}`); 85 | } 86 | }, 2000); 87 | -------------------------------------------------------------------------------- /src/second-demo/client-emitter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Client A Net Connection with Server with emit severals message second by second Without Close Socket. 3 | */ 4 | 5 | /** Require generics dependences */ 6 | import net from 'net'; 7 | import pino from 'pino'; 8 | import connection from '../config/connection.js'; 9 | 10 | // Set pino for get pretty logs. 11 | const logger = pino({ 12 | prettyPrint: { colorize: true } 13 | }) 14 | 15 | // Define main variables. 16 | let clientId; 17 | 18 | const client = net.createConnection({ 19 | host: connection.HOST, 20 | port: connection.PORT, 21 | }, () => { 22 | logger.info('Connected with server!'); 23 | }); 24 | 25 | client.on('connect', () => { 26 | logger.info('Client connected'); 27 | }); 28 | 29 | client.on('ready', () => { 30 | logger.info('Client ready'); 31 | }); 32 | 33 | client.on('data', (data) => { 34 | // Clear terminal. 35 | process.stdout.write('\x1b[2J'); 36 | // Resolve data buffer. 37 | const body = JSON.parse(data.toString()); 38 | // If message is a object, search clientId to send message to others clients via server. 39 | if (typeof body === 'object' && body.clientId) { 40 | clientId = body.clientId; 41 | // Show Message. 42 | logger.info(body.message); 43 | } 44 | }); 45 | 46 | client.on('end', () => { 47 | logger.info('Disconnected from server'); 48 | }); 49 | 50 | // Interval to get clientId and if exist send message to server. 51 | setInterval(() => { 52 | // Send messages to others clients via server. 53 | if (clientId) { 54 | // Clear terminal. 55 | process.stdout.write('\x1b[2J'); 56 | // Send message to others clients. 57 | const body = { 58 | clientId, 59 | message: `Hi ALL from Client: ${clientId}, this is a timestamp: ${Date.now()}` 60 | }; 61 | client.write(JSON.stringify(body)); 62 | // Show log with message sent. 63 | logger.info(body.message); 64 | } 65 | }, 2000); 66 | -------------------------------------------------------------------------------- /src/second-demo/client-receiver.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Client A Net Connection with Server with emit severals message second by second Without Close Socket. 3 | */ 4 | 5 | /** Require generics dependences */ 6 | import net from 'net'; 7 | import pino from 'pino'; 8 | import connection from '../config/connection.js'; 9 | 10 | // Set pino for get pretty logs. 11 | const logger = pino({ 12 | prettyPrint: { colorize: true } 13 | }) 14 | 15 | // Define main variables. 16 | let clientId; 17 | 18 | const client = net.createConnection({ 19 | host: connection.HOST, 20 | port: connection.PORT, 21 | }, () => { 22 | logger.info('Connected with server!'); 23 | }); 24 | 25 | client.on('connect', () => { 26 | logger.info('Client connected'); 27 | }); 28 | 29 | client.on('ready', () => { 30 | logger.info('Client ready'); 31 | }); 32 | 33 | client.on('data', (data) => { 34 | logger.warn(data); 35 | // Clear terminal. 36 | process.stdout.write('\x1b[2J'); 37 | // Resolve data buffer. 38 | const body = JSON.parse(data.toString()); 39 | // Show message from server. 40 | logger.info(body.message); 41 | }); 42 | 43 | client.on('end', () => { 44 | logger.info('Disconnected from server'); 45 | }); 46 | -------------------------------------------------------------------------------- /src/second-demo/server-dispatcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Create Net Server and two clients and send Message to differents client Pear to Pear. 3 | */ 4 | 5 | /** Require generics dependences */ 6 | import net from 'net'; 7 | import pino from 'pino'; 8 | import connection from '../config/connection.js'; 9 | 10 | // Set pino for get pretty logs. 11 | const logger = pino({ 12 | prettyPrint: { colorize: true } 13 | }) 14 | 15 | // Define main variables. 16 | let server; 17 | const clients = []; 18 | 19 | // Function to show clients number connected. 20 | const showClientsConnected = () => { 21 | server.getConnections((err, count) => { 22 | if (err) throw err; 23 | logger.info(`Connections Number: ${count} and Clients registerd in array: ${clients.length}`); 24 | }); 25 | }; 26 | 27 | // Function to send message to all clients. 28 | const broadcastEmitter = (data) => { 29 | // Resolve data buffer and parse to JSON. 30 | const body = JSON.parse(data.toString()); 31 | // If message is a object, search clientId to send message to others clients via server. 32 | if (typeof body === 'object' && body.clientId) { 33 | clients.forEach((client) => { 34 | if(client.id !== body.clientId) { 35 | client.write(JSON.stringify({ 36 | message: body.message, 37 | })); 38 | } 39 | }) 40 | } 41 | } 42 | 43 | // Remove client from array 44 | const removeClient = (clientId) => { 45 | // Get index position of client into array by id. 46 | const index = clients.findIndex((e) => e.id === clientId); 47 | // Remove client from array by index. 48 | clients.splice(index, 1); 49 | } 50 | 51 | // Function to register client into array clients for set an id. 52 | const registerClient = (socket) => { 53 | // Generate Id from timestamp. 54 | const id = Date.now(); 55 | 56 | // Define socket local to save all object. 57 | const _socket = socket; 58 | _socket.id = id; 59 | 60 | // Add into clients array a new client reference. 61 | clients.push(_socket); 62 | 63 | // Send message to client with custom id. 64 | _socket.write(JSON.stringify({ 65 | clientId: id, 66 | message: `Your Client Id is: ${id}` 67 | })); 68 | 69 | // On received data sent to all others clients that are waitting a message. 70 | _socket.on('data', (data) => { 71 | // Data Listener. 72 | logger.warn(`Data received`); 73 | 74 | // Emit message to all clients. 75 | broadcastEmitter(data); 76 | }); 77 | 78 | _socket.on('end', () => { 79 | // End Listener. 80 | logger.warn(`Client disconnected with id: ${_socket.id}`); 81 | 82 | // Remove Client by Id 83 | removeClient(_socket.id); 84 | 85 | // Show Clients number connected. 86 | showClientsConnected(); 87 | }); 88 | _socket.pipe(_socket); 89 | }; 90 | 91 | // Create Server Net. 92 | server = net.createServer((socket) => { 93 | // Connection Listener. 94 | logger.warn('Client connected'); 95 | 96 | // Show Clients number connected. 97 | showClientsConnected(); 98 | 99 | // Register client into array for send message to a client. 100 | registerClient(socket); 101 | }); 102 | 103 | server.on('error', (err) => { 104 | logger.error(err); 105 | }); 106 | 107 | // Define host and port of server. 108 | server.listen({ 109 | host: connection.HOST, 110 | port: connection.PORT, 111 | }, () => { 112 | // Get and show info of server. 113 | const info = server.address(); 114 | logger.info(`Server Net actived on: ${info.address} and port: ${info.port}`); 115 | }); 116 | --------------------------------------------------------------------------------