1. Analyse d'ouverture
À partir d'aujourd'hui, apprenons en détail dans des modules spécifiques. Cet article est le troisième article de cette série. Les deux premiers articles sont principalement basés sur la théorie. Je crois que dans l'étude des deux premiers articles,
J'ai aussi une compréhension de base des nodejs, ça va! ! ! Frappez pendant que le fer est chaud, continuons à transporter des nodejs jusqu'à la fin. Eh bien, sans dire beaucoup de bêtises, allez directement au sujet d'aujourd'hui "Net Module". Alors, comment "net" devrait-il comprendre cela?
À quoi sert-il? ( Net peut être utilisé pour créer des serveurs de socket ou des clients de socket. Les deux modules les plus élémentaires pour la communication de données NodeJS sont Net et HTTP. Le premier est une encapsulation basée sur TCP, tandis que le second est essentiellement une couche TCP, mais elle a fait beaucoup d'encapsulation de données, que nous considérons comme une couche de présentation).
Ici, nous nous référons au code source dans Nodejs "http.js":
Il n'est pas difficile de voir dans la figure que HTTPServer hérite de la classe nette, a des capacités de communication connexes et a fait plus d'encapsulation de données, que nous considérons comme une couche de représentation plus avancée.
Connaissances étendues (ce qui suit est le code source des "hérités"):
La copie de code est la suivante:
export.inherits = function (ctor, superctor) {
ctor.super_ = superctor;
ctor.prototype = object.create (superctor.prototype, {
Constructeur: {
Valeur: ctor,
Énumérable: faux,
Écrivable: vrai,
configurable: vrai
}
});
};
La fonction consiste à réaliser l'héritage et la réutilisation.
Je viens de donner un bref aperçu, qui contient des concepts couramment utilisés. Voici une brève introduction aux concepts de popularisation:
(1) Le protocole TCP / IP ---------- TPC / IP est un protocole de couche de transport, qui résout principalement la transmission des données sur le réseau.
(2), socket ----- La prise est l'encapsulation et l'application du protocole TCP / IP (niveau de programme).
(3), HTTP ------ HTTP est un protocole de couche d'application, qui résout principalement comment envelopper les données.
(4) Le modèle de réseau à sept couches ------------------------------------------------------------------------------------------------------------------
Pour résumer: Socket est une encapsulation du protocole TCP / IP. Le socket lui-même n'est pas un protocole, mais une interface d'appel (API).
Cela forme certaines des interfaces fonctionnelles les plus élémentaires que nous connaissons, telles que créer, écouter, connecter, accepter, envoyer, lire et écrire, etc.
TCP / IP n'est qu'une pile de protocole, tout comme le mécanisme de fonctionnement du système d'exploitation, il doit être implémenté en détail, et il fournit également des interfaces de fonctionnement externes.
En fait, le TCP de la couche de transport est basé sur le protocole IP de la couche réseau, et le protocole HTTP de la couche d'application est basé sur le protocole TCP de la couche de transport. La prise elle-même n'est pas un protocole. Comme mentionné ci-dessus, il ne fournit qu'une interface pour la programmation TCP ou UDP.
Deuxièmement, expérimentez-le
Ok, nous avons le concept, prenons un exemple:
1. Créer server.js
La copie de code est la suivante:
var net = require ('net');
var server = net.createServer (fonction (c) {// écouteur de connexion
console.log ("serveur connecté");
c.on ("end", fonction () {
console.log ("Server a été déconnecté");
});
C.Write ("Hello, BigBear! / R / N");
C.Pipe (c);
});
server.Listen (8124, function () {// écouteur d'écoute
console.log ("Server Bound");
});
2. Créer Client.js
La copie de code est la suivante:
var net = require ('net');
var client = net.connect ({
Port: 8124
}, function () {// Connecter l'écouteur
console.log ("Client Connected");
client.write ('Bonjour, bébé! / r / n');
});
client.on ("data", fonction (data) {
console.log (data.toString ());
client.end ();
});
client.on ("end", function () {
console.log ("Client Disconnect");
});
Analysons:
Server ------ net.createServer crée un service TCP. Ce service est lié (server.Listen) sur le port 8124. Après avoir créé le serveur, nous voyons une fonction de rappel.
Lors de l'appel de la fonction ci-dessus, un paramètre est également une fonction, et il accepte le socket, un tuyau construit par d'autres méthodes, et sa fonction est pour l'interaction des données.
Le tuyau doit être accueilli par le client pour l'établir. S'il n'y a pas d'accès client au serveur en ce moment, cette prise n'existera pas.
Comme son nom l'indique,客户端------net.connect est connecté au serveur. Le premier paramètre est un objet. Le port (port) est défini sur 8124, qui est le port auquel notre serveur écoute. Étant donné que le paramètre hôte n'est pas défini, la valeur par défaut est localhost (local).
Dans le serveur, la prise est une extrémité du pipeline, et dans le client, le client lui-même est une extrémité du pipeline. Si plusieurs clients sont connectés au serveur, le serveur créera plusieurs sockets et chaque socket correspond à un client.
Résultats en cours:
3. Introduction du cas
(1) Le code suivant n'est que le serveur diffusant un morceau de texte au client pour terminer la communication unidirectionnelle du serveur au client.
La copie de code est la suivante:
// Sever -> Communication unidirectionnelle du client
var net = require ('net');
var ChatServer = net.CreateServer ();
ChatServer.on ('Connection', fonction (client) {
client.write ('Hi! / N'); // Le serveur publie des informations au client et utilise la méthode écrite ()
client.write ('bye! / n');
client.end (); // Le serveur termine la session
});
ChatServer.Listen (9000);
Test de Telnet: Telnet127.0.0.1: 9000
Après avoir exécuté Telnet, connectez-vous au point de service, comment les personnages de HI! Au revoir!, Et terminer immédiatement le programme du serveur et terminer la connexion.
Et si nous voulons que le serveur se connecte aux informations au client?
Vous pouvez écouter l'événement server.data et ne pas interrompre la connexion (ou cela mettra immédiatement fin des messages du client qui ne peuvent pas être acceptés).
(2), écoutez l'événement Server.Data et n'abandonnez pas la connexion (sinon, les messages du client ne pourront pas être acceptés immédiatement).
La copie de code est la suivante:
// basé sur le premier, implémenter le client -> Sever Communication, qui est une communication bidirectionnelle
var net = require ('net');
var Chatserver = net.createServer (),
clientList = [];
ChatServer.on ('Connection', fonction (client) {
// JS peut ajouter librement des propriétés aux objets. Ici, nous ajoutons un attribut personnalisé du nom pour indiquer quel client (l'adresse + le port du client est basé)
client.name = client.RemoteAddress + ':' + client.RemotePort;
client.write ('hi' + client.name + '! / n');
clientList.push (client);
client.on ('data', fonction (data) {
diffusion (données, client); // accepter les informations du client
});
});
Fonction Broadcast (message, client) {
pour (var i = 0; i <clientList.length; i + = 1) {
if (client! == clientList [i]) {
clientList [i] .write (client.name + "dit" + message);
}
}
}
ChatServer.Listen (9000);
Est-ce que ce qui précède est un code complet? Nous avons dit qu'il y avait un autre problème qui n'a pas été pris en compte: c'est-à-dire qu'une fois qu'un client sortira, il reste dans la liste client, ce qui est évidemment un pointeur nul.
(3) Processus ClientList
La copie de code est la suivante:
ChatServer.on ('Connection', fonction (client) {
client.name = client.remoteaddress + ':' + client.remoteport
client.write ('hi' + client.name + '! / n');
clientList.push (client)
client.on ('data', fonction (data) {
diffusion (données, client)
})
client.on ('end', function () {
clientList.splice (clientList.Indexof (client), 1); // Supprimez l'élément de formule dans le tableau.
})
})
NodetCPAPI nous a fourni un événement final, c'est-à-dire lorsque le client interdit la connexion au serveur.
(4) Optimiser la diffusion
La copie de code est la suivante:
Fonction Broadcast (message, client) {
Var Cleanup = []
pour (var i = 0; i <clientList.length; i + = 1) {
if (client! == clientList [i]) {
if (clientList [i] .Witable) {// Vérifiez si les prises sont en premier
clientList [i] .write (client.name + "dit" + message)
} autre {
CleanUp.push (clientList [i]) // S'il n'est pas écrit, collectez-le et détruisez-le. Avant la destruction, Socket.Destroy () doit être détruit par l'API.
ClientList [i] .destroy ()
}
}
} // supprimer les nœuds morts hors de la boucle d'écriture pour éviter l'indice de boucle de saut
pour (i = 0; i <cleanup.length; i + = 1) {
clientList.splice (clientList.Indexof (Cleanup [i]), 1)
}
}
Notez qu'une fois que la «fin» n'est pas déclenchée, une exception se produira, de sorte que le travail d'optimisation sera effectué.
(5) NetAPI propose également un événement d'erreur pour attraper les exceptions des clients
La copie de code est la suivante:
client.on ('error', fonction (e) {
console.log (e);
});
Quatre, résumons
1. Comprendre les concepts pertinents du début
2. Comprendre la relation entre les modules HTTP et Net
3. Sur la base des exemples de cet article, veuillez vous référer aux API pertinentes pour pratiquer.
4. Idées de communication entre le client de socket et le serveur
5. Si vous êtes intéressé, vous pouvez améliorer l'exemple de cette salle de chat