记一次使用socket.io的天坑

记一次使用socket.io的天坑

这里是废话(介绍了下socket 和 两个api文档地址)

webscoket可以在用户的浏览器和服务器之间打开交互式通信会话。

使用此API,您可以向服务器发送消息并接收事件驱动的响应,无需通过轮询服务器的方式以获得响应

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.js

import 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})

    });

  });

}

你可能感兴趣的:(热爱,vue.js,javascript,node.js)