什么是webSocket?怎么使用webSocket中的第三方socket.io包
http 协议
-
http中文意思: 超文本传输协议, 定义服务器和客户端的传送格式 -
请求发送的数据包, 叫请求报文, 格式如下
- 响应回来的数据包, 叫响应报文, 格式如下
HTTP 协议:客户端与服务器建立通信连接之后,服务器端只能被动地响应客户端的请求,无法主动给客户端发送消息。
一次请求才能对应一次响应
由于 http 是一次请求对应一次响应,无法达到即时通信的效果,所以在后面的 html5 中提出了一个新的协议 websocket 来实现即时通信的效果
什么是 websocket
websocket 是一种网络通信协议,是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通 信的协议,这个对比着 HTTP 协议来说,HTTP 协议是一种无状态的、无连接的、单向的应 用层协议,通信请求只能由客户端发起,服务端对请求做出应答处理。HTTP 协议无法实现 服务器主动向客户端发起消息,websocket 连接允许客户端和服务器之间进行全双工通信, 以便任一方都可以通过建立的连接将数据推送到另一端。websocket 只需要建立一次连接, 就可以一直保持连接状态
socket.io包使用
1. 安装socket.io包
npm install socket.io-client@4.0.0 -D
yarn add socket.io-client@4.0.0 -D
2. 在组件内引入包
import { io } from 'socket.io-client'
let socket = null
3. 创建socket服务
created() {
socket = io('http://地址', {
query: {
token: this.token
},
transports: ['websocket']
})
}
4. 监听是否连接成功
只有连接内置事件执行了, 才能进行后续操作
created() {
socket.on('connect', () => {
console.log('与服务器建立了连接')
})
}
5. 在组件销毁前, 关闭服务
beforeDestroy() {
socket.close()
socket = null
},
6. 在created监听socket的消息
created() {
socket.on('message', data => {
this.list.push({
name: 'xs',
msg: data.msg
})
})
},
7. 在 send事件中, 把服务器发来的数据装到数组里
sendFn () {
if (!this.word) return
this.list.push({
name: 'me',
msg: this.word
})
}
8. 客户端调用 socket.emit('message', 消息内容) 方法把消息发送给 websocket 服务器
sendFn () {
if (!this.word) return
this.list.push({
name: 'me',
msg: this.word
})
socket.emit('message', {
msg: this.word,
timestamp: new Date().getTime()
})
this.word = ''
}
例
客服小思机器人
<template>
<div class="container">
<!-- 固定导航 -->
<van-nav-bar fixed left-arrow @click-left="$router.back()" title="小思同学"></van-nav-bar>
<!-- 聊天主体区域 -->
<div class="chat-list">
<div v-for="(item, index) in list" :key="index">
<!-- 左侧是机器人小思 -->
<div class="chat-item left" v-if="item.name === 'xs'">
<van-image fit="cover" round src="https://img.yzcdn.cn/vant/cat.jpeg" />
<div class="chat-pao">{{ item.msg }}</div>
</div>
<!-- 右侧是当前用户 -->
<div class="chat-item right" v-else>
<div class="chat-pao">{{ item.msg }}</div>
<van-image fit="cover" round :src="$store.state.photo" />
</div>
</div>
</div>
<!-- 对话区域 -->
<div class="reply-container van-hairline--top">
<van-field placeholder="说点什么..." v-model="word">
<template #button>
<span style="font-size:12px;color:#999" @click="sendFn">提交</span>
</template>
</van-field>
</div>
</div>
</template>
<script>
import store from '@/store/index.js'
import { io } from 'socket.io-client'
export default {
name: 'Chat',
data() {
return {
word: '',
socket: null,
list: [
{ name: 'xs', msg: 'hi,你好!我是小思' },
{ name: 'me', msg: '我是编程小王子' }
]
}
},
methods: {
sendFn() {
this.socket.emit('message', {
msg: this.word,
timestamp: Date.now()
})
this.list.push({ name: 'me', msg: this.word })
this.word = ''
this.$nextTick(() => {
const height1 = document.querySelector('.chat-list').clientHeight
const height = document.querySelector('.chat-list').scrollHeight
document.querySelector('.chat-list').scrollTop = height - height1
})
}
},
created() {
this.socket = io('http://url地址', {
query: {
token: store.state.token
},
transports: ['websocket']
})
this.socket.on('connect', () => {
console.log('与服务器建立了连接')
})
this.socket.on('message', data => {
this.list.push({ name: 'xs', msg: data.msg })
this.$nextTick(() => {
const height1 = document.querySelector('.chat-list').clientHeight
const height = document.querySelector('.chat-list').scrollHeight
document.querySelector('.chat-list').scrollTop = height - height1
})
})
}
}
</script>
<style lang="less" scoped>
.container {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
box-sizing: border-box;
background: #fafafa;
padding: 46px 0 50px 0;
.chat-list {
height: 100%;
overflow-y: scroll;
.chat-item {
padding: 10px;
.van-image {
vertical-align: top;
width: 40px;
height: 40px;
}
.chat-pao {
vertical-align: top;
display: inline-block;
min-width: 40px;
max-width: 70%;
min-height: 40px;
line-height: 38px;
border: 0.5px solid #c2d9ea;
border-radius: 4px;
position: relative;
padding: 0 10px;
background-color: #e0effb;
word-break: break-all;
font-size: 14px;
color: #333;
&::before {
content: '';
width: 10px;
height: 10px;
position: absolute;
top: 12px;
border-top: 0.5px solid #c2d9ea;
border-right: 0.5px solid #c2d9ea;
background: #e0effb;
}
}
}
}
}
.chat-item.right {
text-align: right;
.chat-pao {
margin-left: 0;
margin-right: 15px;
&::before {
right: -6px;
transform: rotate(45deg);
}
}
}
.chat-item.left {
text-align: left;
.chat-pao {
margin-left: 15px;
margin-right: 0;
&::before {
left: -5px;
transform: rotate(-135deg);
}
}
}
.reply-container {
position: fixed;
left: 0;
bottom: 0;
height: 44px;
width: 100%;
background: #f5f5f5;
z-index: 9999;
}
</style>
text-align: left;
.chat-pao {
margin-left: 15px;
margin-right: 0;
&::before {
left: -5px;
transform: rotate(-135deg);
}
}
}
.reply-container {
position: fixed;
left: 0;
bottom: 0;
height: 44px;
width: 100%;
background: #f5f5f5;
z-index: 9999;
}
</style>
效果
|