【即时通讯 Socket.io】vue+express.js+Socket.io简易聊天室

动画.gif

Socket.io介绍

Socket.IO 不是 WebSocket实现。Socket.io库也有用到WebSocket协议,但是对不支持WebSocket的浏览器会回退到HTTP轮询,还提供自动重连,是一个更高级的库。

① Express.js 安装 Socket.io

至少需要 Node.js 10,不再支持旧版本。
npm install socket.io

使用HTTP服务器 初始化

Socket.IO 实例的 options 配置

const { createServer } = require("http");
const { Server } = require("socket.io");

const httpServer = createServer();
const io = new Server(httpServer, { /* options */ });

io.on("connection", (socket) => {
// ...
});
//3002端口作为ws使用 在这里使用app.listen(3002)将不起作用,因为它会创建一个新的 HTTP 服务器。
httpServer.listen(3002);

② Vue客户端 安装 Socket.io及配置

npm i vue-socket.io -S
npm i socket.io-client -S

使用socket.io-client连接

// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import VueSocketIO from 'vue-socket.io';
import SocketIO from 'socket.io-client'

Vue.use(new VueSocketIO({
debug: true, // debug调试,生产建议关闭
connection: SocketIO('ws://localhost:3002')
}))

new Vue({
// 这里为全局监听socket事件消息,监听函数这里只写了一点,其实很有很多事件。
// 也可以在组件内单独监听
sockets: {
connecting() {
console.log('正在连接')
},
disconnect() {
console.log("Socket 断开");
},
connect_failed() {
cosnole.log('连接失败')
},
connect() {
console.log('socket connected')
}
},
router,
store,
render: h => h(App)
}).$mount('#app')

组件内使用

<template>
<div class="about">
<h1>WEB Sockt.io</h1>
<div class="main">
<el-row>
<el-col :span="16">
<el-input id='input' v-model="input"></el-input>
</el-col>
<el-col :span="8">
<el-button type="primary" @click="sendMsg">Send</el-button>
</el-col>
</el-row>
<div id="content"></div>
</div>
</div>
</template>
<script>
const ENTER = 0
const LEAVE = 1
export default {
data() {
return {
input: '',
content: '',
message: ''
}
},
sockets: {
connect() {
this.$message({
message: '连接成功!!!',
type: 'success'
})
},
disconnect() {
this.$message({
message: '连接断开!!!',
type: 'error'
})
},
broadcast_msg(data) {
console.log('接收到服务器数据,',data)
var content = document.querySelector('#content')
var div = document.createElement('div')
div.innerText = `${data.msg} ---${data.time}`
if (data.type === ENTER) {
div.style.color = 'green'
} else if (data.type === LEAVE) {
div.style.color = 'red'
} else {
div.style.color = 'blue'
}
content.appendChild(div)
}
},
methods: {
sendMsg() {
this.$socket.emit('send_msg', this.input)
}
},
mounted() {
this.$socket.open()
},
destroyed() {
console.log('destroyed,')
},
beforeDestroy() {
this.$socket.close()
},
created() {
//连接
this.$socket.open()
// 查看socket是否连接成功
// this.$socket.connected()
}
}
</script>
<style lang="scss" scoped>
.about {
padding: 20px;
.main {
width: 500px;
}
#input {
width: 10px;
}
#content {
margin-top: 15px;
text-align: left;
}
}
</style>

Express服务端完整代码

// app.js
const http = require('http')
const server = http.createServer(app)
server.listen(3002) // 这是ws端口和普通接口用的端口是:app.listen(3000)要区分开
require('./utils/utils.socket').listen(server)
// utils.socket.js
const {Server} = require("socket.io");
const chalk = require('chalk')
exports.listen = function (server) {
const io = new Server(server, {
cors: {
origin: '*'
}
});

const ENTER = 0
const LEAVE = 1
const MESSAGE = 2
let count = 0
io.on('connection', socket => {
console.log(chalk.blue('用户已连接'))
count++
let user = `用户${count}`
io.sockets.emit('broadcast_msg',
{
type: ENTER,
msg: `${user}加入群聊`,
time: new Date().toLocaleString()
}
)
socket.on('send_msg', (data) => {
console.log(`收到客户端的消息:${data}`)
io.sockets.emit('broadcast_msg', {
type: MESSAGE,
msg: `${user}:${data}`,
time: new Date().toLocaleString()
})
})
socket.on('disconnect', () => {
console.log(chalk.red('用户已离开'))
io.sockets.emit('broadcast_msg', {
type: LEAVE,
msg: `${user}离开了群聊`,
time: new Date().toLocaleString()
})
count--
});
});
return io.listen(server);
};

vue客户端启动项目控制台就可以看到连接ws成功

image.png

Express服务端启动连接成功信息

image.png