Socket. IO implements chat rooms
Socket. IO Chinese document
Realtime application framework
Socket. IO is simply the encapsulation of Websocket, excluding client-side JS and server-side Node. js. Its purpose is to build real-time application problems in different browsers and devices, such as: no one ordering food, instant communication, etc
Example: Implementing chat rooms
Based on Node + Express + socket. IO + vue + Flex to achieve chat room
Functions:
- Login to detect
- System prompts online personnel status (enter/leave)
- Receive and send messages
- Customize message font colors
- Support for sending emojis
- Support sending window vibration
Initialize and install dependencies
npm init --yes
npm i express socket.io -s
Copy the code
Integrated socket. IO
Socket. IO consists of two parts
- Server that integrates with node.js HTTP service: socket.io
- Client library loaded in the browser: socket. IO -client
Socket. IO will automatically serve us during development, as you can see, with only one module to install
server.js
const express = require('express')
const app = express()
// Bind server app to HTTP instance
const http = require('http').Server(app)
// Pass the HTTP server instance object to initialize the new instance of socket. IO
// The HTTP module listens for connection events coming into the socket and logs them to the console
const io = require('socket.io')(http)
// Set the static resource root directory
app.use('/', express.static(__dirname + '/static'))
app.get('/'.(req, res) = > {
res.sendFile(__dirname + '/index.html')})// IO binding events connection Establishment disconnected connection disconnected
io.on('connection'.socket= > {
console.log('A user creates a link');
// Socket binding event, the client triggers the addCart event to send data
socket.on('addCart'.data= > {
console.log(data);
// socket.emit represents sending messages to the current person
// IO. Emit delegates send messages to everyone
socket.emit('to-client', {
server: 'Here's the data from the server.'
})
})
})
http.listen(3000.() = > {
console.log('Listen on port 3000');
})
Copy the code
Note that port 3000 is listened on through an HTTP instance
static/index.js
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<h1>The chat room</h1>
<button id='btn'>Add shopping cart</button>
<! -- Client socket. IO -->
<script src="js/socket.io.min.js"></script>
<script>
console.log(io);
</script>
</body>
</html>
Copy the code
After socket. IO is imported, the system automatically creates AN I/O object and prints the result
Go ahead, set the server address, and get the button-click event
Declare socket.emit to send requests and socket.on to receive messages from the server
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<h1>The chat room</h1>
<button id='btn'>Add shopping cart</button>
<! -- Client socket. IO -->
<script src="js/socket.io.min.js"></script>
<script>
// Call the IO method to pass in the server address and return the socket object.
const socket = io('http://localhost:3000')
document.querySelector('#btn').onclick = () = > {
// Send a request through socket.emit. The first parameter is the event bound in the server's socket.on and the second parameter is the data to send
socket.emit('addCart', {
msg: 'This is a message from the client.'
})
// To receive requests through socket.on, the first parameter is the event to be triggered by the server, and the second parameter is the message sent by the server
socket.on('to-client'.data= > {
console.log(data); })}</script>
</body>
</html>
Copy the code
Chat room example
index.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="style/index.css">
<link rel="stylesheet" href="Style/font - awesome - 4.7.0 / CSS font - awesome. Min. CSS">
</head>
<body>
<div id="app">
<div class="name" v-if='isShow'>
<! -- <h2> Please enter your nickname </h2> -->
<input type="text" v-model='username' id="name" placeholder="Please enter a nickname..." autocomplete="off"
@keyup.enter='handleClick'>
<button id="nameBtn" @click='handleClick'>determine</button>
</div>
<! -- Whole window -->
<div class="main" :class='{shaking:isShake}'>
<div class="header">
<img src="image/logo.jpg">❤ ️ chat room</div>
<div id="container">
<div class="conversation">
<ul id="messages">
<li v-for='(user,i) in userSystem' :key='i' :class='user.side'>
<! -- Panel where the current user sends messages -->
<div v-if='user.isUser'>
<! -- User avatar -->
<img :src="user.imgSrc" alt="">
<div>
<span>{{user.name}}</span>
<! -- User information display -->
<p v-html='user.msg' :style='{color:user.color}'>
</p>
</div>
</div>
<p class='system' v-else>
<span>{{nowDate}}</span><br />
<span v-if='user.status'>{{user.name}}{{user.status}} in the chat room</span>
<span v-else>{{user.name}} sent a window jitter</span>
</p>
</li>
</ul>
<! -- Form processing for sending messages -->
<form action="">
<! Send the control above -->
<div class="edit">
<input type="color" id="color" v-model='color'>
<i title="Customize font colors" id="font" class="fa fa-font">
</i><i title="Double click to deselect" class="fa fa-smile-o" id="smile" @click='handleSelectEmoji' @dblclick='handleDoubleSelectEmoji'>
</i><i title="Click page vibrate" id="shake" class="fa fa-bolt" @click='handleShake'>
</i>
<input type="file" id="file">
<i class="fa fa-picture-o" id="img"></i>
<! -- Expression management -->
<div class="selectBox" v-show='isEmojiShow'>
<div class="smile" id="smileDiv">
<p>A classic expression</p>
<! -- Emoji -->
<ul class="emoji">
<li v-for='(emojiSrc,i) in emojis' :key='i'>
<img :src="emojiSrc" :alt="i+1" @click='handleEmoji(i)'>
</li>
</ul>
</div>
</div>
</div>
<! -- AutoComplete disables autocomplete -->
<textarea id="m" autofocus v-model='msgVal'></textarea>
<button class="btn rBtn" id="sub" @click='handleSendMsg'>send</button>
<button class="btn" id="clear" @click='handleCloseMsg'>Shut down</button>
</form>
</div>
<! -- Online personnel display -->
<div class="contacts">
<h1>Online staff (<span id="num">{{userInfo.length}}</span>)</h1>
<ul id="users">
<li v-for='(user,i) in userInfo' :key='i'>
<img :src="user.imgSrc" alt="">
<span>{{user.username}}</span>
</li>
</ul>
<p v-if='userInfo.length === 0'>No one is online at present</p>
</div>
</div>
</div>
</div>
<script src="./js/socket.io.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src='js/client.js'></script>
</body>
</html>
Copy the code
client.js
new Vue({
el: "#app".data() {
return {
isShow: true.username: ' '.// The current user name
userSystem: [].// Stores the current user's state and message array
nowDate: new Date().toTimeString().substr(0.8),// The current time
userInfo: [].// Current user information
msgVal: ' '.// Message content
color: '# 000000'.// Font color
isEmojiShow: false.// Emoticons are hidden by default
emojis: [].// An array of emoticons
isShake:false.timer:null,}},methods: {
// Click the smiley event
handleSelectEmoji() {
this.isEmojiShow = true;
},
// Double-click the smiley to cancel the event
handleDoubleSelectEmoji() {
this.isEmojiShow = false;
},
handleEmoji(i) {
// Handle the emoticon click event
this.isEmojiShow = false;
this.msgVal = this.msgVal + `[emoji${i}] `
},
// Click ok
handleClick() {
const imgN = Math.floor(Math.random() * 4) + 1; // Randomly assign 1, 2, 3, 4
if (this.username) {
this.socket.emit('login', {
username: this.username,
imgSrc: `image/user${imgN}.jpg`})}},handleSendMsg(e) {
// The event that sent the message vue event modifier
e.preventDefault();
if (this.msgVal) {
this.socket.emit('sendMsg', {
msgVal: this.msgVal,
color: this.color
/ / color
})
this.msgVal = ' '; }},handleCloseMsg(e) {
// Click the close button to operate
e.preventDefault();
this.isEmojiShow = false;
this.msgVal = ' ';
},
initEmoji() {
for (let i = 1; i <= 141; i++) {
this.emojis.push(`image/emoji/emoji (${i}).png`)}},scrollBottom(){
// After DOM rendering is complete, an internal callback is performed
this.$nextTick(() = >{
const oDiv = document.getElementById('messages'); oDiv.scrollTop = oDiv.scrollHeight; })},handleShake(){
// The method of vibration
this.socket.emit('shake');
},
shake(){
// The method of vibration
this.isShake = true;
clearTimeout(this.timer);
this.timer = setTimeout(() = > {
this.isShake = false;
}, 500); }},created() {
// Initialize render emoticons
this.initEmoji();
const socket = io();
this.socket = socket;
this.socket.on('loginSuc'.() = > {
console.log('Login successful');
this.isShow = false;
})
this.socket.on('loginError'.() = > {
alert('Username duplicate, please re-enter');
this.username = ' ';
})
this.socket.on('system'.(user) = > {
// {name:" xiao Ma ",status: "enter"}
this.userSystem.push(user);
this.scrollBottom();
})
this.socket.on('disUser'.(userInfo) = > {
this.userInfo = userInfo;
})
this.socket.on('receiveMsg'.(user) = > {
let { msg } = user;
let content = ' ';
while (msg.indexOf('[') > -1) {
// Have emoticons render
const start = msg.indexOf('[');
const end = msg.indexOf('] ');
content += `<span>${msg.substr(0, start)}</span>`;
content += `<img src="image/emoji/emoji%20(${msg.substr(start + 6, end - start - 6)}).png" alt=""/>`
msg = msg.substr(end + 1, msg.length);
}
content += `<span>${msg}</span>`
user.msg = content;
// Color display
// emoticons render
// Make sure the scroll bar is always at the bottom
this.userSystem.push(user);
// Make sure the scrollbar is always below
this.scrollBottom();
})
// Listen for vibration events
this.socket.on('shake'.(data) = >{
this.userSystem.push(data);
// Handle page vibrations
this.shake();
// Scroll to the bottom
this.scrollBottom(); })}})Copy the code
server.js
const express = require('express');
const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
// Set the static resource root directory
app.use('/', express.static(__dirname + '/static'));
app.get('/'.function (req, res) {
res.sendFile(__dirname + '/index.html');
})
let users = [];// An array of current user names
let userInfo = [];// Store the current user information
io.on('connection'.function (socket) {
console.log('Establish server side link');
// Listen for login messages sent by the client
socket.on('login'.function (user) {
const { username } = user;
if (users.indexOf(username) > -1) {
// The user name is repeated
socket.emit('loginError')}else {
users.push(username);
userInfo.push(user);
// Store the current user name
socket.nickName = username;
// Notifies the client of successful login
io.emit('loginSuc');
// Marco enters the chat room
io.emit('system', {
name: username,
status: '进入'
})
// Display the online person and return a message to the client
io.emit('disUser', userInfo);
console.log('A user has logged in'); }})// Listen for sending message events
socket.on('sendMsg'.(data) = > {
let imgSrc = ' ';
// The profile address of the user who sent the message is the name of the user because socket.nickname is the name stored for the current user
for (let i = 0; i < userInfo.length; i++) {
if(userInfo[i].username === socket.nickName){ imgSrc = userInfo[i].imgSrc; }}// Broadcast to everyone except the sender
socket.broadcast.emit('receiveMsg', {
name: socket.nickName,
imgSrc:imgSrc,
msg:data.msgVal,
color:data.color,
// Color type
side:'left'.isUser:true,
})
socket.emit('receiveMsg', {name: socket.nickName,
imgSrc: imgSrc,
msg: data.msgVal,
color: data.color,
// Color type
side: 'right'.isUser: true,})})// Send window vibration event
socket.on('shake'.() = >{
socket.emit('shake', {name:'you'
})
// Broadcast messages to other users
socket.broadcast.emit('shake', {name:socket.nickName
})
})
// Disconnect the link
socket.on('disconnect'.() = > {
// [a,b,c] //1 users userInfo
let index = users.indexOf(socket.nickName);
if (index > -1) {
users.splice(index, 1); // Delete the user name
userInfo.splice(index, 1);// Delete user information
// Notify the client when XXX leaves
io.emit('system', {
name: socket.nickName,
status: 'leave'
})
// Tell the client to rerender
io.emit('disUser', userInfo); }})}); http.listen(3000.() = > {
console.log('listen on 3000 port! ');
})
Copy the code
conclusion
The service side
IO. On (‘ connection ‘, function (socket)); // Listen for client connections. The callback function passes the socket for the connection
IO. Sockets. Emit (” String “, data); // Broadcast messages to all clients
IO. Sockets. The socket (socketid.) emit (” String “, data); // Send a message to the specified client
Socket. On (‘ String ‘, function (data)); // Listen for messages sent by the client
Socket. Emit (” String “, data); // Send a message to the socket client
Broadcast messages
// Broadcast socket.broadcast.emit(" MSG ",{data:"hello,everyone"}); // Broadcast socket.broadcast.emit(" MSG ",{data:"hello,everyone"}); // Broadcast io.sockets. Emit (" MSG ",{data:"hello,all"});Copy the code
grouping
socket.on('group1', function (data) {
socket.join('group1');
});
socket.on('group2',function(data){
socket.join('group2');
});
Copy the code
Client send
Socket. emit(‘ group1 ‘) and add to group1; Socket. emit(‘ group2 ‘) and add to group2;
A client can have multiple groupings (subscription mode)
Play group
socket.leave(data.room);
Sends messages to users in a group
To ('group1').emit('event_name', data); // include IO.sockets. In ('group1').emit('event_name', data);Copy the code
The broadcast method allows the current socket client to be excluded from the packet
Gets the client socket for the connection
io.sockets.clients().forEach(function (socket) {
//.....
})
Copy the code
Obtaining Group Information
/ / get all the rooms (branch) information IO. Sockets. The manager. The rooms / / IO socketid into the room to get this information. The sockets. Manager. RoomClients [socket. Id] / / access to particular Io.sockets. Clients (' Particular room')Copy the code
Another way of grouping
io.of('/some').on('connection', function (socket) {
socket.on('test', function (data) {
socket.broadcast.emit('event_name',{});
});
});
Copy the code
The client
Var socket = IO. Connect (ws: / / 103.31.201.154:5555 / 'some') socket. On (' even_name ', function (data) {the console. The log (data); })Copy the code
The client is linked to ws://103.31.201.154:5555 but the server can filter it out by IO. Of (‘ /some ‘).
IO provides four configuration apis: IO. Configure, IO. Set, IO. Enable, and IO. IO. Set sets a single item, and IO. Enable and IO. Disable are used for Boolean configuration of a single item. IO. Configure lets you configure different parameters for different production environments such as Devlopment, Test, and so on.
The client
Set up a socket connection
Var socket = IO (” ws: / / 103.31.201.154:5555 “);
Listening for service messages
socket.on('msg',function(data){ socket.emit('msg', {rp:"fine,thank you"}); // Sends messages to the server console.log(data); });Copy the code
Socket.on (” String “,function(data)) listens for the message sent by the server. The Sting parameter is the same as the first parameter emitted by the server
The listening socket is disconnected and reconnected.
Socket. on('disconnect', function() {console.log(" disconnects from the server "); }); Socket. on('reconnect', function() {console.log(" reconnect "); });Copy the code
Client socket.on() listens for:
Connect: The connection succeeds
Connecting: Indicates that a connection is being established
Disconnect: Disconnects the connection
Connect_failed: The connection fails
Error: An error occurs and cannot be handled by other event types
Message: same as the message event on the server
Anything: The same as the server anything event
Reconnect_failed: Reconnection failed
Reconnect: Successful reconnect
Reconnecting: Indicates a reconnection is taking place
When connecting for the first time, events are triggered in the following sequence: connecting-> Connect. When a connection is lost, the event is triggered in the following sequence: disconnect->reconnecting ->connecting->reconnect->connect.
The related documents
Tutorial document
Socket. IO tutorial | development institute (kaifaxueyuan.com)
vue-socket.io
Vue-socket. IO Tutorial and Pit log – Dreamsqin – Blogpark (CNblogs.com)