前几天在网上看到了关于websocket的一些视频教程,所以就在学习了以后做了这个项目,总结一下在做这个项目过程中遇到的一些问题

效果图

图片经过压缩,展示效果不是很好

 

 

关于socket通信的简单说明

Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信(来源百科)。它是一种全双工(服务端与客户端可同时收发消息)通信,当有数据更新时服务端可以主动的将消息推送到客户端。

Socket通信的运行流程如下

1、服务端启动Socket监听端口,监听是否有客户端连接进来,即Watch Socket;

2、客户端通过http协议发送请求报文,服务端响应请求后会将协议升级为WebSocket,并创建一个新>的Socket对象,客户端Socket随即与服务端Socket进行连接和通信,且客户端不再与Watch Socket通信;

3、Watch Socket继续监听是否有其它客户端连接。

项目地址

基于vue+koa2+socket.io实现多人在线实时聊天(客户端)

后端

技术栈

  • node
  • koa2
  • socket.io

socket.io的使用

socket.io提供了基于事件的实时双向通讯,它同时提供了服务端和客户端的API。

服务端

服务端socket.io必须绑定一个http.Server实例,因为WebSocket协议是构建在HTTP协议之上的,所以在创建WebSocket服务时需调用HTTP模块并调用其下createServer()方法,将生成的server作为参数传入socket.io。

 

var httpServer = require('http').createServer();

var io = require('socket.io')(httpServer);

httpServer.listen(3000);

项目代码

socket.on( ) :订阅一个事件
socket.emit( ) : 告诉当前用户
io.emit( ) : 广播事件

const Koa = require("koa")

const app = new Koa()

const cors = require("koa2-cors")

 

// 解决跨域

app.use(cors())

 

//核心,初始化app作为HTTP 服务器的回调函数像express这么写mac电脑会有问题,无法访问

// const server = require('http').Server(app);  //express写法

const server = require('http').Server(app.callback());  //koa正确姿势

const io = require('socket.io')(server); //核心,实现客户端之间交互通信

 

let users = []  //存储所有用户的数组

 

io.on("connection", socket => {

    socket.on("submit", (data) => {

        let result = users.find(item => {

            return item.userName == data.userName

        })

        socket.emit("login", result)

        if (!result) {

            // 存储当前登陆用户的信息

            socket.userName = data.userName

            socket.avatar = data.avatar

 

            // 加入到用户数组

            users.push(data)

            socket.emit("loginSuccess", data)

 

            io.emit("addUser", data)

            io.emit("userList", users)

        }

    })

 

    //发送信息

    socket.on("sendMsg", data => {

        io.emit("sendAll", data)

    })

 

    //发送图片

    socket.on("sendFile", data => {

        io.emit("sendFileAll", data)

    })

 

    // 用户断开连接的时候

    socket.on('disconnect', () => {

        // 把当前用户的信息从users中删除掉

        let idx = users.findIndex(item => item.userName === socket.userName)

        // 删除掉断开连接的这个人

        users.splice(idx, 1)

        // 1. 告诉所有人,有人离开了聊天室

        io.emit('delUser', {

            userName: socket.userName,

            avatar: socket.avatar

        })

        // 2. 告诉所有人,userList发生更新

        io.emit('userList', users)

    })

})

 

server.listen(3000, () => {

    console.log(`监听地址: http://localhost:3000`);

})

前端

技术栈

  • vue
  • vue-socket.io
  • scss

vue-socket.io

vue-socket.io使用

socket.io 的github地址

安装

npm install vue-socket.io --save

 

引入

//main.js

import VueSocketIO from 'vue-socket.io'

 

Vue.use(new VueSocketIO({

  debug: true, //设置true可以让你的控制台文字变颜色,更好的调试阅读

  connection: 'http://localhost:3000',

}))

 

vue-socket.io订阅事件

注意:这段代码是和你的methods、mounted等生命周期同级的
(vue-socket.io 3.0.9版本因为出现了无法触发sockets里订阅的事件的bug,所以尽量不要使用3.0.8,和3.0.9版本的,也有解决办法,后面会讲)

sockets:{

    connect(data){

      if(data){

        console.log('连接成功',data)

        this.$socket.emit("users")

      }

    },

    users(data){

      console.log("在线人数",data)

      this.userNmber = data;

    },

    reconnect(data){

      console.log('重新连接',data)

    },

    disconnecting(data){

      console.log('socket已断开连接');

      this.$socket.emit("users")

    },

    getMsg(data){

      console.log("后端传过来的消息",data)

      this.speak = data

    }

  }

关于 vue-socket.io 3.0.8版本和3.0.9版本存在的bug

在 vue-socket.io 3.0.9 版本中会出现无法接收到信息的 bug (也就是你在 sockets中定义的方法是没有办法触发的) ,关于这个问题我们可以通过以下方法解决

方法一: this.sockets.listener.subscribe

this.sockets.listener.subscribe("事件名", (参数) => {

    //逻辑

})

方法二 :使用 socket.io-client

import io from 'socket.io-client'

export default {

  mounted() {

    io('http://127.0.0.1:8080').on('hi', (res) => {

      console.log('socket.io-client', res)

    })

  },

}

以上两种解决办法可以文章 :vue-socket.io3.08,3.09有bug接收不到数据

方法三:回退版本到 3.0.7

这个版本是不存在该bug的

vue 渲染页面后div的滚动条保持在最底部的方法

因为在用户发送信息时,我们需要实时查看到最新的休息,所以需要让滚动条保持到最底部,在网上查看了好几种方法,但是在vue中还是有些不太适用,但是还是记录下来

关于$nextTick

Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM

方式一:

 

//每次页面渲染完之后滚动条在最底部

updated:function(){

    this.$nextTick(function(){

    var p = document.getElementById('dialogue_box');

    p.scrollTop = p.scrollHeight;

    })

  }

方式二:

亲测该方法在发送图片时会有bug

//processData 是双向绑定的数据

watch: {

    'processData': 'scrollToBottom'

  }

  methods:{

   scrollToBottom: function () {

    this.$nextTick(() => {

      var div = document.getElementById('data-list-content')

      div.scrollTop = div.scrollHeight

    })

   }

  }

转自http://www.yemengs.cn/article?id=5ecb913c401f514d37d6e0d4&distance=0&page=2

 

 

 

 

Logo

前往低代码交流专区

更多推荐