热爱|记一次使用socket.io的天坑
记一次使用socket.io的天坑
这里是废话(介绍了下socket 和 两个api文档地址) webscoket可以在用户的浏览器和服务器之间打开交互式通信会话。
使用此API,您可以向服务器发送消息并接收事件驱动的响应,无需通过轮询服务器的方式以获得响应
【热爱|记一次使用socket.io的天坑】webscoket文档
还有一个比较细的文章webscoket - socket.io
将webscoket到scoket.io都讲了一遍?
在平常的开发中 也多使用scoket.io居多,因为它解决了很多类似于兼容性
的问题。
下面的例子我们也使用它来做。
具体的api还需要看这个中文文档 scoket.io
有几个常用的api
- on : 监听约定的事件
- emit : 触发指定的事件
- broadcast.emit : 事件广播 (广播给
除自己以外
的所有人)
- io.to(clientId) : 向指定的人广播
跨域
和无法连接
的问题。 可能都是一个问题。那就是使用后端socket.io的版本太高,或者和前端使用的socket.io-client的版本不匹配。
如果不匹配可能会发生一些奇怪的问题。
我这里说以下我前端和后端的各自使用的版本。
前端:
vue3
socket.io-client@1.4.5后端:
koa@2.7.0
socket.io@1.4.5
前端如下:
// 终端
npm i socket.io-client@1.4.5
随后我们在vue3种建立一个 io 插件 并且将它注入到全局。
// io.jsimport io from 'socket.io-client'export default {install: (app, {
connection, options }) => {const socket = io(connection, options)
// 这里是vue3新的全局注入这样你可以在非Setup 中 使用 this.$socket 调用这个io连接。
app.config.globalProperties.$socket = socket
// 在setup中 你可以使用Provide / inject 得到socket很简单吧.
app.provide('socket', socket)
}
}
// 在main.js中使用这个插件import SocketIO from 'io.js'import {
createApp } from 'vue'import App from './App.vue'createApp.use(SocketIO,{connection: 'http://127.0.0.1:9090/typing'
})
// vue3组件中使用// 我们可以使用 provide 和 inject 对。父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。
// 这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这个数据。import {
inject } from "vue";
export const socketIo = () => {// 之前在插件中使用了provide 注入了 socket
// 在这里我们需要使用 inject 来获取它
const msgSocket = inject('socket');
// 更新自己数据
msgSocket.on('init', (data) => {console.log(data)})
}
服务端挂载有两种方式
// 方式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, {cors:true,
serveClient: false,
// below are engine.IO options
pingInterval: 10000,
pingTimeout: 5000,
cookie: false
});
// www文件const app = require('../app');
const debug = require('debug')('demo:server');
const http = require('http');
const port = normalizePort(config.port);
const server = http.createServer(app.callback());
const typing = require('../utils/typing');
const io = require('socket.io')(server,{cors:true,
serveClient: false,
pingInterval: 10000,
pingTimeout: 5000,
});
typing(io);
// typing.js// 封装了以下游戏的js module.exports = (io) => {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]) {console.log(data)
typing.to(data.clientId).emit('send_request_to_client', {clientId: client.id
});
}
})// 监听用户点击接受请求
client.on('request_ok_to_server', (data) => {// 建立链接
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})
})// 监听清除
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})});
});
}
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- 20170612时间和注意力开销记录
- 2018年11月19日|2018年11月19日 星期一 亲子日记第144篇
- 叙述作文
- 2019年12月24日
- 【故障公告】周五下午的一次突发故障
- 人生感悟记#环境仪器宋庆国成长记#072
- 2019.4.18感恩日记
- 我要我们在一起(二)