websocket

作者: 他爱在黑暗中漫游 | 来源:发表于2018-05-27 09:09 被阅读13次

    websocket 是什么?

    websocket 是随着 HTML5 一起出的一个全新的通信协议, 在 websocket 被提出之前,浏览器与服务器之间通信是通过 http 或者 https 协议来完成的。

    首先 http 协议本身是非常棒的,我非常喜欢它。但是它自身也有一些不足点,无论是之前的 http 1.0 的短连接还是现在的 http 1.1 长连接, 都不能做到让服务器主动的推送消息给浏览器,必须是浏览器主动发出 request, 然后服务器再被的 response。

    始终是 【浏览器 主动 requiest】 => 【服务器 被 response】这种模式。

    为什么服务器不能主动一点,前端妹子要走啦!!!! 哈哈哈哈.....

    为了应对 http 协议的这个不足点, HTML5 中就出了 websocket 协议这个小家伙, 她能让服务器主动推送消息给浏览器


    websocket-server-edit.jpg http-server-edit.jpg

    websocket 与 http 在与服务器通信时都需要先与服务器建立连接, 建立连接的过程她们几乎是一样的。

    建立连接之后:

    http 与 服务器进行进行通信时只能是【浏览器 主动 requiest】 => 【服务器 被 response】这种模式。

    但是使用 websocket 协议时,则没有主动与被一说,浏览器与服务器之前可以相互任意的发送消息。 不再是一个 request 对应一个 response 的模式了。

    说了这么多,其实 websocket 也只不过是众多协议中的一个协议而已。

    兼容性

    websocket-compatibility.png

    如何使用 websocket ?

    任何协议都是需要通信双方皆支持时才可以使用的,在支持 websocket 协议的浏览器中可以直接使用相关的 API, 并且服务器也需要支持 websocket 才可以。(服务器是不能使用 http 协议与浏览器端 websocket协议进行通信, 这就好像中文件和英文之间也是不可能直接通信的)

    浏览器端代码:

    // WebScoket 支持 websocket 的浏览器会提供一个全局的 WebSocket
    var wsUri = 'ws://127.0.0.1:8080/'
    var websocket = new WebSocket(wsUri)
    websocket.onopen = function (event) {
      // 这里执行时表明,已经使用 websocket 协议与服务器建立好了连接,可以相互的发送消息了
      console.log('websocket 连接建立成功!')
    }
    

    node.js 端代码

    可以使用一个叫ws 的第三方模块,它帮我们实现好了 websocket 协议,可以直接在 node.js 中使用

    npm install ws —save
    
    const WebSocket = require('ws');
    const wsServer = new WebSocket.Server({ port: 8080 })
    wsServer.on('connection', function connection(client) {
      // 这里执行时表明,已经使用 websocket 协议与服务器建立好了连接,可以相互的发送消息了
      console.log('websocket 连接建立成功!')
    })
    

    哈哈是不是感觉和浏览器端的代码几乎一样,哈哈~ 就是这么神奇!

    🚩 参考示例代码: demo/建立websocket连接 目录中

    使用 websocket 发送消息

    连接成功之后,就可以调用上面两个实例各自的send方法来相互发送消息了

    只有连接成功之后才可以发消息!

    websocket.onopen = function () {
      ws.send('消息')
    }
    
    wsServer.on('open', function () {
      
    })
    

    websocket 相关事件

    浏览器端:

    // WebScoket 支持 websocket 的浏览器会提供一个全局的 WebSocket
      var wsUri = 'ws://127.0.0.1:8080/'
      var websocket = new WebSocket(wsUri)
      // websocket 事件:
      // open 事件: 连接建立成功后触发
      websocket.onopen = function (event) {
        // 这里执行时表明,已经使用 websocket 协议与服务器建立好了连接,可以相互的发送消息了
        console.log('websocket 连接建立成功!')
        console.log('open', event)
        websocket.send('发给服务器的消息')
        // websocket.close() // 是关闭连接的方法
      }
      // message事件: 服务器发来消息时触发
      websocket.onmessage = function (event) {
        // event.data 是服务器发来的消息内容
        console.log('message', event)
      }
      // close 事件: 连接关闭时触发
      websocket.onclose = function (event) {
        console.log('close', event)
      }
      // error 事件: 连接发生错误时触发(例如网络中断时)
      websocket.onerror = function (event) {
        console.log('error', event)
      }
    

    node.js 端

    const wsServer = new WebSocket.Server({ port: 8080 })
    const wsServer = new WebSocket.Server({ port: 8080 })
    wsServer.on('connection', function connection (ws) {
      // 这里执行时表明,已经使用 websocket 协议与服务器建立好了连接,可以相互的发送消息了
      console.log('websocket 连接建立成功!')
      ws.send('发给前端的消息')
      // ws.close() 是关闭连接的方法
      ws.on('message', function (data) {
        console.log('message', data)
      })
      ws.on('close', function (errcode) {
        console.log('close', errcode)
      })
      ws.on('error', function (err) {
        console.log('error', err)
      })
    })
    

    🚩 参考示例代码: demo/websocket消息与事件 目录中

    服务器端广播

    给所有人广播消息

    wsServer.clients.forEach(function each(client) {
        if (client.readyState === WebSocket.OPEN) {
          client.send('广播消息')
        }
    }
    

    给除了当前发出请求人之外的人广播

    wss.clients.forEach(function each(client) {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send('广播消息');
      }
    }
    

    SSE

    SSE (Server-Sent Events,服务器发送事件 )

    兼容性

    sse-compatibility.png

    socket.io

    socket.io 是什么?

    socket.io 不是一个具体的技术,而是一个基于 websocket 等即时通讯手段封装的一个库。

    使用它时可以不必担心长轮询写法麻烦,也不必担心 websocket 兼容性问题,这些问题,socket.io 都会帮我们处理好。

    如何使用 socket.io ?

    使用的方式和 websocket 大抵差不多
    node.js 端

    结合 express 框架的代码

    const http = require('http')
    const express = require('express')
    const socketIO = require('socket.io')
    const app = express()
    const server = http.createServer(app)
    // 将和 http 监听相同的端口
    const io = socketIO(server)
    
    app.use(express.static('./public'))
    app.use(express.static('./node_modules'))
    // 有客户端连接事件
    io.on('connection', (socket) => {
      // 当有客户端连接时执行, 参数 socket 就代表当前连接上来的客户端
      console.log('a user connected')
    })
    
    server.listen(3000, '127.0.0.1', err => {
      if (err) {
        return console.log(err)
      }
      console.log('启动成功: http://127.0.0.1:3000/index.html')
    })
    
    

    浏览器端:

    需要引入 socket.io.js 文件, 它在 node_modules/socket.io-client/dist/socket.io.js , 是随着 socket.io 一同被下载下来的。

    <script src="/socket.io-client/dist/socket.io.js"></script>
    <script>
      // 与服务器建立连接, 连接的服务器地址不需要提供, 默认就是当前地址栏的地址。
      // io 是 socket.io.js 中暴露的全局变量
      var socket = io();
    </script>
    

    socket.io 相关事件及消息的发送与接收

    node.js 端

    // connection 有客户端连接事件, 通过 io 这个对象来监听
    io.on('connection', (socket) => {
      // disconnect 是连接断开事件, 通过 socket 这个客户端对象监听
      socket.on('disconnect', () => {
        
      })
      // 当 on 的参数1 不是上面的 connection 或者 disconnect 这种 socket.io 自带的事件时, 它就相当于是自定义事件,用来接收浏览器发来的消息
      socket.on('yyy', msg => {
        // 参数 msg 就是浏览器发来的消息
        console.log(msg)
      })
      // emit 方法的作用是主动给浏览发送消息, 浏览器中也有一个 emit 方法,作用是主动给服务器发送消息
      socket.emit('xxx', '要发送的消息内容')
    })
    

    浏览器端

    var socket = io()
      socket.on('connect', function () {
        console.log('连接建立成功!')
      })
      // 接收服务器通过 socket.emit('xxx',) 发来的消息
      // 服务器端 emit 方法的参数1 需要和这里的 on 方法的参数1 相同时这里的回调才会执行。
      socket.on('xxx', function (msg) {
        console.log(msg)
      })
      
      document.querySelector('form').onsubmit = function (e) {
        e.preventDefault()
        var oIpt = document.querySelector('input')
        socket.emit('yyy', oIpt.value)
        oIpt.value = ''
      }
    

    socket.io 广播

    node.js 端

    socket.emit() // 给自己回发
    socket.broadcast.emit // 给除自己外的人发
    io.emit() // 给所有人发
    

    相关文章

      网友评论

        本文标题:websocket

        本文链接:https://www.haomeiwen.com/subject/mhxbjftx.html