back to top

Creare un semplice server TCP in Node.js

In questa lezione della nostra guida a Node.js vedremo come usare il modulo net per creare una semplicissima chat da usare nel terminale. Per far ciò creeremo un banale server e useremo un programma come telnet per collegarci al server creato. Inoltre, utilizzeremo alcuni package esterni che scaricheremo con l’aiuto di NPM.

Per prima cosa creiamo una nuova cartella, ci spostiamo al suo interno e inizializziamo il progetto col comando npm init. Dopo aver completato i campi necessari, verrà creato un file package.json.

Installiamo poi alcuni package con l’aiuto di NPM.

  • chalk per stampare dei messaggi con diversa formattazione e colore;
  • figlet per creare arte ascii;
  • uniqid per generare identificativi univoci per ogni client che desidera collegarsi al server;
  • nodemon per evitare di dover riavviare il server ad ogni modifica effettuata;

Installiamo con il seguente comando tutti i package tranne nodemon. In questo modo abbiamo aggiunto tutti i moduli installati alla lista delle dipendenze.

npm install chalk figlet uniqid --save

A questo punto installiamo nodemon che aggiungeremo all’elenco delle dipendenze necessarie solo in fase di sviluppo.

npm install nodemon --save-dev

Modifichiamo il file package.json come mostrato in basso.

{
  "name": "semplice_chat",
  "version": "1.0.0",
  "description": "Una semplice chat tcp",
  "main": "server.js",
  "scripts": {
    "dev": "nodemon server.js",
    "start": "node server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^2.1.0",
    "figlet": "^1.2.0",
    "uniqid": "^4.1.1"
  },
  "devDependencies": {
    "nodemon": "^1.12.1"
  }
}

Grazie a nodemon, in fase di sviluppo, non dobbiamo riavviare manualmente il server ogni volta che effettuiamo una modifica.

Possiamo iniziare a scrivere il nostro semplice server utilizzando il modulo net. Creiamo un file server.js come quello mostrato in basso. Si tratta di un’implementazione elementare con diversi limiti, realizzata con il solo scopo di mostrare come iniziare a usare le funzioni fornite dal modulo net.

const chalk = require('chalk');
const uniqid = require('uniqid');
const figlet = require('figlet');
const net = require('net');
const server = net.createServer();

let sockets = {};

const PORT = 3000 || process.env.PORT;
const ADDRESS = '127.0.0.1' || process.env.ADDRESS;
const FULL_ADDRESS = `${ADDRESS}:${PORT}`;

server.on('connection', (socket) => {

  socket.id = uniqid();
  console.log(`Utente con id=${socket.id} connesso`);

  socket.write(chalk.yellow(figlet.textSync('Simple Chat')) + 'nn');
  socket.write('? Inserisci il tuo nome: ');

  socket.on('data', (data) => {
    if (!sockets[socket.id]) {

      socket.name = data.toString().trim();

      if (socket.name) {
        // aggiungi l'utente all'elenco degli utenti collegati
        sockets[socket.id] = socket;

        socket.write(chalk.green(`Benvenuto ${socket.name}n`));
        // Mostra nel terminale dell'utente un prompt personalizzato
        socket.write(`[ ${socket.name} ] > `);

      } else {
        // se il nome inserito non è valido, il client visualizzerà un messaggio
        // e verrà chiusa la connessione
        socket.end(chalk.red.bold('ERRORE! Nome non valido!n'));

      }
    } else {

      Object.keys(sockets).forEach((id) => {
        const otherUser = sockets[id];
        // invia il messaggio spedito da un utente a tutti gli altri
        if (socket.id !== id) {
          otherUser.write(`n${socket.name}: ${data}`);
          otherUser.write(`[ ${otherUser.name} ] > `);
        } else {
          // aggiorna il prompt dell'utente che ha inviato il messaggio
          socket.write(`[ ${socket.name} ] > `);
        }
      });

    }
  });

  socket.on('end', () => {
    delete sockets[socket.id];
    console.log(`${socket.name} ha lasciato la chat.`);
  })
});

server.listen(
  PORT,
  ADDRESS,
  () => console.log(`
  =============================

   +++ Server in funzione +++  

  Indirizzo: ${chalk.green(FULL_ADDRESS)}

  =============================
  `)
);

Per prima cosa, abbiamo importato i moduli esterni che ci aiuteranno a realizzare il server TCP. Inizializziamo quindi un oggetto sockets che useremo per tener traccia di tutti i client che si collegheranno al server. Dichiariamo alcune costanti che utilizziamo poi all’interno della funzione server.listen() con la quale mettiamo in ascolto il server all’indirizzo e porta specificati come argomenti. La prima volta che un nuovo utente si collega, sarà emesso l’evento ‘connection’ che useremo per assegnargli un nuovo codice identificativo (socket.id). All’utente sarà inoltre chiesto di inserire il proprio nome. Quando un client invia un messaggio al server, se non è ancora presente nell’elenco degli utenti collegati, (ovvero se è il primo messaggio inviato) viene aggiunto all’oggetto sockets. (sockets è un oggetto avente come proprietà i codici identificativi univoci degli utenti) In caso contrario, il server invia il messaggio spedito da un client a tutti gli altri utenti.

Per per avviare il server appena creato, lanciamo il seguente comando nel terminale.

npm start
output del terminale dopo l'esecuzione del comando npm start per avviare il server

Ora possiamo aprire due nuove finestre del terminale e collegarci al server usando un programma come telnet. Lanciamo quindi il seguente comando nelle due finestre appena aperte per collegarci all’indirizzo 127.0.0.1 specificando il numero di porta. (3000)

telnet 127.0.0.1 3000
messaggio di benvenuto ricevuto da un client che si connette al server tcp

Come potete vedere dall’immagine, il client si collega al server e visualizza l’ascii art (Simple Chat). Gli viene quindi chiesto di inserire il proprio nome. A questo punto è pronto per iniziare a inviare dei messaggi agli altri utenti collegati.

Possiamo quindi provare a inviare un messaggio da un client all’altro.

invio messaggio da parte di un utente collegato al server tcp

Per terminare una sessione, possiamo digitare la sequenza di escape (^]), cioè digitare il carattere ‘]’ mentre teniamo premuto il tasto CTRL.

Chiusura connessione da parte di un client della chat TCP

Conclusioni

Abbiamo visto come creare un semplicissimo server TCP usando il modulo net e alcuni moduli ausiliari che abbiamo aggiunto al nostro progetto attraverso NPM. Nella prossima lezione vedremo come realizzare un banale server HTTP usando l’omonimo modulo.

Pubblicitร