Maison >interface Web >js tutoriel >Introduction au didacticiel d'apprentissage socket.io dans node.js (3)
Cet article vous présente les informations pertinentes de socket.io de manière plus approfondie. Les didacticiels et applications de base de socket.io ont déjà été présentés. Cet article présente l'utilisation de socket.io de manière plus approfondie. Vous pouvez l'utiliser comme référence, jetons un œil ci-dessous.
Avant-propos
Socket.io fournit une communication bidirectionnelle en temps réel basée sur des événements. Cet article présente socket.io en profondeur. jetez un oeil. Contenu détaillé.
Fichiers statiques
socket.io fournit par défaut socket.io.min via le package socket.io-client Télécharger. js et socket.io.js.map
Exécutez l'instance app.js
let app = require('http').createServer() let io = require('socket.io')(app) app.listen(3000);
Accès au navigateur http://localhost:3000/socket.io/socket io. .js peut charger du code source compressé, visitez http://localhost:3000/socket.io/socket.io.js.map pour charger sourcemap
Nous pouvons modifier ce comportement
Désactiver le téléchargement de socket.io.js
Méthode 1 : transmettre le paramètre de contrôle valeur serveClient false lors de l'instanciation
let io = require('socket.io')(app, { serveClient: false })
méthode 2 : Appelez la fonction serverClient
let app = require('http').createServer() let io = require('socket.io')() io.serveClient(false) io.listen(app) // 或者io.attach(app)
Si le service a été liéhttp.Server
avant d'appeler la fonction, cette méthode ne fonctionnera pas
Si vous y accédez à nouveau après l'avoir désactivé, vous être invité{"code":0,"message":"Transport unknown"}
Modifier le chemin du fichier statique
Le chemin socket.io.js peut être modifié, et son le chemin par défaut est /socket.io.
Transmettre les paramètres lors de l'instanciation
let io = require('socket.io')(app, { path: '/io' })
Chemin de la fonction d'appel
let app = require('http').createServer() let io = require('socket.io')() io.path('/io') io.listen(app)
Si le service a été lié avant d'appeler la fonctionhttp.Server
, cette méthode ne fonctionnera pas Fonction
Politique de sécurité
socket.io fournit deux politiques de sécurité
allowRequest
La fonction allowRequest a deux paramètres. Le premier paramètre est l'objet du paquet de poignée de main reçu (http.request
), qui est utilisé comme base pour le jugement, le succès), err est l'objet d'erreur et le succès est booléen, false signifie empêcher l'établissement d'une connexion
La requête frontale apporte un jeton
let socket = io('http://localhost:3000?token=abc') socket.on('connect', () => { console.log('connect') }) socket.on('connect_error', err => { socket.disconnect() console.log('connect_error', err) })
Le back-end AllowRequest détermine s'il faut continuer en fonction du jeton
let app = require('http').createServer() let io = require('socket.io')(app, { allowRequest: (req, cb) => { if (req._query && req._query.token === 'abc') return cb(null, true) cb(null, false) } });
origines
Vous pouvez limiter la source
1 Limiter la source lors de l'instanciation
let app = require('http').createServer() let io = require('socket.io')(app, { origins: 'http://localhost:3000' })
2. . La fonction origines définit la source
La fonction origines a deux formes
origins(string)
: Définir la source de l'opération
. origins(string, fn(err, success))
: Utilisez la fonction pour déterminer si la source est autorisée
io.origins('http://localhost:*') io.origins((origin, cb) => { if (origin === 'http://localhost:3000/') return cb(null, true) cb(null, false) })
Espace de noms
L'espace de noms est utilisé pour isoler connexions serveur/client. À certains endroits, les espaces de noms sont également appelés canaux (canal). L'exemple suivant explique son importance
Nous devons mettre en œuvre une application collaborative, qui a deux fonctions :
Édition collaborative : plusieurs utilisateurs peuvent modifier un document en même temps
Message : les utilisateurs peuvent envoyer des messages entre utilisateurs
Utilisez socket.io pour implémenter cette application, qui a les formes suivantes
1. Complètement indépendant : Il existe un service indépendant pour l'édition collaborative edit.socket.test
, et un service indépendant pour la messagerie message.socket.test
let editSocket = io('edit.socket.test') let messageSocket = io('message.socket.test')
2. Namespace : Un seul service indépendant est exécuté, via l'espace de noms Isolation
let app = require('http').createServer() let io = require('socket.io')(app) let editServer = io.of('/edit') let messsageServer = io.of('/message') editServer.on('connection', socket => { //编辑相关 }) messsageServer.on('connection', socket => { /消息相关 })
let editSocket = io('socket.test/edit') let messageSocket = io('socket.test/message')
3. Convention de nom d'événement : Isolation en ajoutant des noms d'événements
let app = require('http').createServer() let io = require('socket.io')(app) io.on('connection', socket => { //编辑相关 io.emit('edit:test') io.on('edit:test', data => { }) //消息相关 io.emit('message:test') io.on('message:test', data => { }) }
La procédure de convention de nom d'événement est trop intrusive et peu propice au fractionnement et à la réorganisation, non recommandé. Le mode totalement indépendant nécessite l'utilisation de deux connexions socket, ce qui gaspille le nombre de connexions simultanées autorisées par le navigateur et consomme plus de ressources du serveur. L'utilisation d'espaces de noms peut obtenir une bonne isolation sans gaspiller de ressources.
Espace de noms par défaut
L'espace de noms avec le chemin / étant automatiquement lié lorsque socket.io est instancié
let app = require('http').createServer() let io = require('socket.io')(app) io.sockets // io.of('/').sockets io.emit // 代理io.of('/').emit, 类似函数有'to', 'in', 'use', 'send', 'write', 'clients', 'compress'
Middleware
L'espace de noms de socket.io enregistre le middleware lors de son utilisation, et le middleware établit avec succès une connexion entre le client et le serveur . Enfin, il est appelé une fois avant la distribution de l'événement connet.
Utiliser un middleware pour la vérification des données
io.use((socket, next) => { if (socket.request.headers.cookie) return next() next(new Error('Authentication error')) })
Utiliser un middleware pour extraire ou convertir des donnéesio.use((socket, next) => { <code>io.use((socket, next) => { <br>getInfo(socket.request.query.id, (err, data) => { if (err) return next(err) socket.custom = data next() }) })
getInfo(socket . request.query.id, (err, data) => { if (err) return next(err) socket.custom = data next() }) })
Comparé avec allowRequest
allowRequest peut effectuer une vérification et une extraction, pourquoi avons-nous besoin d'un middleware ?
allowRequest entrant l'instance http.request, tandis que le middleware entre et sort de l'instance de socket de données, l'instance de socket contient l'instance de requête et contient plus d'informations
Le middleware prend directement en charge l'imbrication de plusieurs processus asynchrones, tandis queallowRequest doit être implémenté par vous-même
Comparaison avec l'événement de connexion
L'événement de connexion est également transmis dans le socket et peut également être utilisé pour les valeurs numériques vérification et extraction. Pourquoi ? Avez-vous besoin d'un middleware ?
Le middleware prend directement en charge l'imbrication de plusieurs processus asynchrones, tandis que allowRequest doit être implémenté par vous-même
中间件成功后到connection事件发送成功前,socket.io还做了一些工作,比如把socket实例添加到connected对象中,加入聊天室等。如果因为权限中断连接,在中间件中处理更省资源.
聊天室
聊天室是对当前连接的socket集合根据特定规则进行归组,方便群发消息。可以类比QQ群的概率.
socket.join('room name') //进入 socket.leave('room name') //退出
io.to('some room').emit('some event') // io.to与io.in同义,向某个聊天室的所有成员发送消息
默认聊天室
每个socket在连接成功后会自动创建一个默认个聊天室,这个聊天室的名字是当前socket的id,可以通过默认聊天室实现向特定用户发送消息
socket.on('say to someone', (id, msg) => { socket.broadcast.to(id).emit('my message', msg) })
消息发送
应答消息
普通消息不需要回应,而应答消息提供了应答机制
io.on('connection', socket => { socket.emit('an event', { some: 'data' }) //普通消息 socket.emit('ferret', 'tobi', function (data) { //应答消息 console.log(data); // data will be 'woot' }) })
socket.on('ferret', (name, fn) => { fn('woot') })
压缩
socket.compress(true)
启用压缩,调用后当前连接的所有数据在传递给客户端前都会进行压缩
volatile标志
socket.io在正常情况下对发送的消息进行追踪,确保消息发送成功,而设置volatile后发送消息,socket.io不会对消息追踪,消息可能丢失
分类
// 客户端发送消息 socket.emit('hello', 'can you hear me?', 1, 2, 'abc'); // 向所有连接的客户端(除了自己)发送消息 socket.broadcast.emit('broadcast', 'hello friends!'); // 向game聊天室发送消息,自己不算 socket.to('game').emit('nice game', "let's play a game"); // 同时向game1和game2聊天室发送消息,自己不算 socket.to('game1').to('game2').emit('nice game', "let's play a game (too)"); // 向game聊天室的所有人发送消息 io.in('game').emit('big-announcement', 'the game will start soon'); // 发送消息到<socketid>客户端 socket.to(<socketid>).emit('hey', 'I just met you'); // 发送应答消息 socket.emit('question', 'do you think so?', function (answer) {});
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!