webscoket
webscoket可以在用户的浏览器和服务器之间打开交互式通信会话。使用此API,您可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。
webscoket是什么/有什么用?
找到一个比较细的文章socket.io
将webscoket到scoket.io都讲了一遍?
在平常的开发中 也多使用scoket.io居多,因为它解决了很多类似于兼容性的问题。
下面的例子我们也使用它来做。
另外我了解到,当你使用scoket.io 那么必须使用对应的 scoket.io-client作为前端的操作工具。
scoket.io 的一些常用api总结。
具体的api请看这个 scoket.io
有几个常用的api
on : 监听约定的事件
-
socket.on()用于监听获取发送过来的数据
-
socket.on('monitorName', callBack)有两个参数:
-
monitorName:监听的标识
-
callBack:是一个回调函数
-
emit : 触发指定的事件 播给 所有人
-
socket.emit()用于发送数据
-
socket.emit('monitorName', sendData)有两个参数:
-
monitorName:监听的标识
-
sendData:可以是字符串,也可以是{}JSON对象,这是向后端发送过去的数据
-
broadcast.emit : 事件广播
- 广播给
除自己以外的所有人
io.to(clientId): 向指定的人广播
- clientId : 指定人的连接ID
webscoket 怎么用(前端)?
拿 vue组件举个例子
假设我们的后端使用的就是scoket.io
那么前端,首先你需要在命令行安装 scoket.io-client
然后在main.js中引用它
如下:
// 终端
npm i socket.io-client
// main.js
import io from 'socket.io-client';
我们通常在mounted中对一些插件进行初始化
{
mounted(){
// 这个实例化需要传递一个地址如:http://localhost:8888/self
let myScoket = io.connect('http://localhost:8888/self')
// 实时监听后端返回数据
myScoket.on('事件名',()=>{
})
// 主动发送给后端数据
myScoket.emit('事件名',()=>{
})
}
}
webscoket 怎么用(后端)?
以nodejs koa2框架为例子
# npm安装socket.io
$ npm install --save socket.io
服务端挂载有两种方式
// 方式1
// 这种方式将和服务公用一个端口 ,但是需要配置 cors:true 来避免跨域
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
var server = http.createServer(app.callback());
const io = require('socket.io')(server,{
cors:true,
serveClient: false,
pingInterval: 10000,
pingTimeout: 5000,
});
server.listen(port);
// 方式2
// 直接定义端口
// 目前看没什么不同
const io = require('socket.io')(3000, {
path: '/path',
serveClient: false,
// below are engine.IO options
pingInterval: 10000,
pingTimeout: 5000,
cookie: false
});
服务端处理链接 和 分发数据.
// 开启一个命名空间
const typing = io.of('typing')
// 设置一个游戏链接池
let games = {}
typing.on('connection', client => {
// 我们每次连接都将连接id 对应为空
if (!games[client.id]) {
games[client.id] = null
}
// 并且广播出去
client.broadcast.emit('userList', {games})
// 这里发现广播不能广播给自己 所以,我们增加一个发送事件把当前的状态给到前端
client.emit('init', {games})
// 检查自己和目标用户是不是已经和别人连接游戏,如果没有就请求连接游戏
client.on("send_request_to_server", (data) => {
if (!games[data.clientId] && !games[client.id]) {
// 使用to函数传入对应的链接id,给对应的链接发送链接请求
typing.to(data.clientId).emit('send_request_to_client', {
clientId: client.id
});
}
})
// 这里我们设置P1 P2 为一组游戏
// 监听用户点击接受请求
client.on('request_ok_to_server', (data) => {
// 我们建立链接 将P1的ID 对应 P2的ID
games[client.id] = data.clientId
games[data.clientId] = client.id
// 并且通知前端 可以开始游戏了
typing.to(client.id).emit('start')
typing.to(data.clientId).emit('start')
client.broadcast.emit('userList', {games})
})
// 我们监听P1清除 然后给P2发送P1状态值
client.on('delete_to_server', (data) => {
let p2 = games[client.id]
if (p2) {
typing.to(p2).emit('delete_to_client', data)
}
})
// 监听添加 原理同上
client.on('push_to_server', (data) => {
let p2 = games[client.id]
if (p2) {
typing.to(p2).emit('push_to_client', data)
}
})
// 断开链接
client.on('disconnect', () => {
// 从游戏池种删除自己
delete games[client.id]
// 断开与游戏好友的游戏
for (const gamesKey in games) {
if (games[gamesKey] === client.id) {
games[gamesKey] = null
}
}
client.broadcast.emit('userList', {games})
});
});