WebSocket 以及 socket.io 使用

WebSocket 以及 socket.io 使用

说明

WebSocket 是一个持久化的协议, 是基于HTTP协议的, 它支持长连接,而不是像 ajax 一样通过轮询,每隔一段时间,向服务器发送请求,询问是否有新的信息,服务器端不能主动联系客户端,只能由客户端发起。对于 WebSocket 它只需要一次对服务器的请求,然后服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息,而且跨域通信。

WebSocket API

不同服务器端语言有不同的 API, 一下主要展示客户端API

1. 创建 WebSocket 实例
    const w = new WebSocket('ws://localhost:8181');

‘ws://localhost:8181’ 表示要连接的URL。这个URL应该为响应WebSocket的地址, ws 表示WebSocket协议。

使用“Echo”服务器:ws://echo.websocket.org 能将发送过去的数据返回, 可以用于测试能否链接上

2. 与服务器建立连接后的回调
  • w.onopen = function(){} 成功建立连接
  • w.send() 向服务器发送数据
  • w.close() 关闭 WebSocket 链接或停止正在进行的链接请求
   w.onopen = function(a) {
      /*
         一旦服务器响应WebSocket 链接请求就会触发open 事件
         open事件触发,意味着握手协议结束,WebSocket已经准备好收发数据,
         如果你的应用收到open事件,就可以确定服务端已经处理了建立连接的请求,且同意和你的应用通信。
      */
      console.log('Connect open...');
      console.log(w);

      /*
         发送一个文本消息,在open之后,或者根据WebSocket对象的状态判断是否open
      */
      w.send('hello websocket');

      if (w.readyState === WebSocket.OPEN) {
         // 状态码 等于 OPEN 的时候
         w.send('is in open');
      }

      // 状态码
      for (let attr in WebSocket) {
         console.log(attr, WebSocket[attr]);
         /*
            CONNECTING   0
            OPEN   1
            CLOSING   2
            CLOSED   3
         */ 
      }
   }
3. 接受服务器消息的回调
  • w.onmessage = function(){}
    w.onmessage = function (e) {
        /*
         接收服务器消息触发的事件
        */
        console.log(e.data); // e.data 服务器返回的数据
        console.log(w);

        /*
         close()用于关闭链接,调用后将不能发送数据
        */
        w.close();
    }
4. 连接失败时触发回调
  • w.onerror = function(){}
    w.onerror = function (e) {
        /*
         失败时触发,错误会导致链接关闭
        */
        console.log(e);
    }
5. 关闭链接时回调
  • w.onclose = function(){}
    w.onclose = function (e) {
        /*
         链接关闭时触发
        */
        console.log('close', e);
    }

Socket.io API

Socket.io是一个完全由JavaScript实现、基于Node.js、支持WebSocket的协议用于实时通信、跨平台的开源框架,它除了支持WebSocket通讯协议外,还支持许多种轮询机制以及其它实时通信方式,并封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。会根据浏览器对通讯机制的支持情况,选择最佳方式实现网络实时通信

官网地址 github地址

1. 安装到项目

npm install --save-dev socket.io

2. 服务器端

服务器端API

1. 创建服务
    const app = require('http').createServer(handler);
    const io = require('socket.io')(app);
    const fs = require('fs');
    const ip = require('ip').address();
    const DB = require('./db.json');
    app.listen(8089, ip);

    function handler (req, res) {
       fs.readFile(__dirname + '../app/index.html',
       function (err, data) {
          if (err) {
             res.writeHead(500);
             return res.end('Error loading index.html');
          }

          res.writeHead(200);
          res.end(data);
       });
    }

    // 客户端就可以通过 `http://${ip}:8089` 建立 websocket 通信了
2. 监听客户端连接
  • socket.on(”, function(data){}) 监听客户端发送的消息
    io.on('connection', function (socket) {
       /*
            监听客户端连接,回调函数会传递本次连接的socket
            回调函数的socket 为一个client与服务器的连接标识,不同client不一样
       */ 

       console.log('connection id = ' + socket.id);

       socket.on('changeswitch', function (data) {
          // 客户端发出的 'changeswitch' 事件的处理函数
          console.log(data);
       })
    })
3. 给客户端发送消息
  • socket.emit(”, {}) 在 connection 回调中使用,将数据传输给对应的客户端
  • socket.broadcast.emit(”, {}) 信息传输对象为所有client,排除当前socket 对应的 client
  • io.socket.emit(”, {}) 信息传输对象为所有client
  • io.sockets.socket(socketid).emit(”, {}) 给指定的客户端发送消息
    io.on('connection', function (socket) {

       socket.on('changeswitch', function (data) {
          setTimeout(function () {
             /*
                socket.emit 信息传输对象为当前socket对应的client,各个client socket 互不影响
                socket.broadcast.emit 信息传输对象为所有client,排除当前socket 对应的 client
                io.socket.emit 信息传输对象为所有client
             */
             io.sockets.emit('changeswitchfinish', {
                success: true,
                switchInfo: data
             });
          }, 500);
       })  
    })
3. 客户端

客户端 API

1. 建立 socket 链接
    import io from 'socket.io-client'; // 注意要引入 -client 的模块否则报错
    import ip from './reuqest'; // ip 是通过 webpack 注入的当前 ip 地址,与配置服务器的地址相同

    const socket = io(`http://${ip}:8089`);

    socket.on('connect', function () {
        console.log('链接成功');
    })
2. 监听服务器消息
  • socket.on(”, function(data){})
    socket.on('connect',function () {
        // 连接成功
    })
    socket.on('connecting',function () {
        // 正在连接
    })
    socket.on('disconnect',function () {
        // 断开连接
    })
    socket.on('connect_failed',function () {
        // 连接失败
    })
    socket.on('error',function () {
        // 报错
    })
    socket.on('reconnect_failed',function () {
        // 重连失败
    })
    socket.on('reconnect',function () {
        // 成功重连
    })
    socket.on('reconnecting',function () {
        // 正在重连
    })
    socket.on('changeswitchfinish', function (data) {
        if (data.success) {
            dispatch({type: CHANGE_SWITCH, msg: data})
        } 
    })
3. 向服务器发送消息
  • socket.emit(”, {}) 使用前要确定与服务器是否链接上

    if (socket.connected) {
        // statement
        socket.emit('changeswitch', {});
    }
4. 主动断开链接
  • socket.disconnect()
5. 问题

结合 react redux 一起使用遇到了一些问题,选择了一些折中的解决办法

在发出的 action 中使用 WebSocket,由于不能每一个 action 都打开一个 Socket 服务,所以 最后 socket 挂在了 window 上。

这样由于多个 action 都需要进行 WebSocket 通信,所以不能再 socket.on(‘connect’,fn) 函数中进行 socket.emit() 或者 socket.on(”,fn),解决办法是在每次使用(socket.connected)判断是否连接到服务器,然后发送消息

socket.on(”,fn) 自定义的操作都要在初始化建立 socket 链接后紧接着定义,不要单独定义在某一个 action 中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值