websocket


  
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>socket测试</title>

    <!-- Bootstrap -->
    <link href="http://cdn.mark.ah.cn/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">

  </head>
  <body>
    <div class="container">
      <form>

        <div class="form-group">
          <label >请输入:</label>
          <input type="text" class="form-control" id="textInput" placeholder="请输入" maxlength="100">
        </div>

        <div class="form-group text-center">

          <button type="button" class="btn btn-info" id="sendBtn">发送</button>

          <button type="button" class="btn btn-warning"  id="clearBtn">清空记录</button>

          <button type="button" class="btn btn-success" id="mockBtn">模拟断开连接</button>

          <button type="button" class="btn btn-danger" id="closeBtn">完整关闭</button>

          <button type="button" class="btn btn-success" id="reConnectBtn">重连</button>

        </div>

        <div class="form-group">
          <label >服务端返回应答消息:</label>
          <div id="respondDiv">
            
          </div>
        </div>

      </form>
    </div>


    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="http://cdn.mark.ah.cn/jquery/1.11.3/jquery-1.11.3.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="http://cdn.mark.ah.cn/bootstrap/3.0.3/js/bootstrap.min.js"></script>
  </body>

  <script type="text/javascript">
    //下划线表示是内部私有方法,推荐外部不进行调用
    $(function (){
      var OriocSocket = function(opt){
        var options = opt || {}
        if (!options.url) {
          options.url = 'ws://192.168.3.250:8263/ws';
        }
        this.options = options;

        //接收到消息的回调处理方法
        this.onMsg = options.onMsg
        //通道开启事件回调
        this.onSocketOpen = options.onSocketOpen
        //通道关闭事件回调
        this.onSocketClose = options.onSocketClose
        //登录回调
        this.onLogin = options.onLogin
        //掉线
        this.onDisconnect = options.onDisconnect

        //loginKey 是socket 通道的唯一识别标志,
        //后端通过这个标志向客户端发送消息
        this.loginKey = options.loginKey

        //初始化
        this.init = function (){
          if (!this._checkUsable()) {
            alert('您的浏览器不支持webSocket');
            return ;
          }
          //默认连接标志为false
          this.socketConnected = false;

          try {
            //初始化socket
            this._initSocket()
            //初始化socket相关事件
            var that = this
            this._initSocketEvents(function (){
              //执行login方法
              that._login(that.loginKey);
              that.socketConnected = true;
            })
          } catch(e) {
            //初始化连接失败
            console.log('初始化连接失败');
            console.log(e);
            this.socketConnected = false;
            this.onDisconnect && this.onDisconnect()
          }
          //初始化心跳连接,在心跳的时候进行连接健康检查,
          //发现有问题直接进行重连
          this._initSocketHeartBeat();
        };

        //发送消息
        this.sendMsg = function (_content){
          if (!this.socketConnected) {
            throw Error('socket通道已关闭')
          }
          this._sendFormattedMsg(this.loginKey,'Publish',_content)
        };

        //主动关闭通道
        //主动关闭之后再次开启需要调用init
        this.close = function (){
          console.log('关闭通道');
          try {
            this.socket && this.socket.close()
          } catch (e) {}
          //清理socket实例
          this.socket = null;
          //清理心跳定时器
          var _interval = this.heartbeatInterval
          if (_interval) {
            try {
              clearInterval(_interval)
              console.log('心跳已关闭')
            } catch (e) {}
          } 
          this.socketConnected = false;
        };

        //模拟断开连接
        //未暂停心跳机制,10秒后会自动重连
        this.mockDisconnect = function (){
          try {
            this.socket.close()
          } catch (e) {}
          this.socketConnected = false;
        };

        //检查是否可用
        this._checkUsable = function (){
          if (!window.WebSocket) {
            window.WebSocket = window.MozWebSocket;
          }
          if (!window.WebSocket) {
            return false;
          }
          return true;
        };
        
        //初始化socket
        this._initSocket = function (){
          var url = this.options.url;
          this.socket = new WebSocket(url);
        };

        //初始化socket事件
        this._initSocketEvents = function (_openedCallback){
          var that = this
          //接收到消息
          that.socket.onmessage = function(event){
            if (!event.data) {
              return ;
            }
            that.onMsg && that.onMsg(event.data); 
          }
          //通道开启
          that.socket.onopen = function (){
            console.log('socket 通道已开启');
            _openedCallback && _openedCallback()
            that.onSocketOpen && that.onSocketOpen()
          }

          //断开,暂时先自动重连
          that.socket.onclose = function (){
            that.onDisconnect && that.onDisconnect()
            that.onSocketClose && that.onSocketClose()
          }

          that.socket.onerror = function (err){
            console.log('socket 异常 ',err);
          }


        };

        //通道开启后执行登录方法
        this._login = function (){
          var that = this
          this._sendFormattedMsg(this.loginKey,'Login', new Date().getTime(),function (err){
              if (err) {
                console.log('登录失败');
              }else{
                that.onLogin && that.onLogin()
              }
          })
        };

        //初始化socket心跳机制
        this._initSocketHeartBeat = function (){
          var _interval = this.heartbeatInterval
          if (_interval) {
            try {
              clearInterval(_interval)
            } catch (e) {}
          } 

          _interval = null;
          //心跳10秒一次
          var that = this
          _interval = setInterval(function (){
            if (that.socket.readyState != that.socket.OPEN) {
              //如果未连接,重新进行连接
              //重连之后直接进行登录
              that._reconnect();
              //连接后重新发送心跳
              that._sendBeatMsg();
            }else{
              //连接后重新发送心跳
              that._sendBeatMsg();
            }
            
          }, 1000*10)
          this.heartbeatInterval = _interval
        };

        //发送心跳数据
        this._sendBeatMsg = function (_callback){
          this._sendFormattedMsg(this.loginKey,'HeartBeat',
            new Date().getTime(),function (err){
              console.log('242 ',err);
              _callback && _callback(err)
          })
        };

        //断线重连
        this._reconnect = function (){
          try {
            this.socketConnected = false;
            //初始化socket
            this._initSocket()
            //初始化socket相关事件
            var that = this
            this._initSocketEvents(function (){
              //执行login方法
              that._login(that.loginKey);
              that.socketConnected = true;
            })
          } catch(e) {
            //初始化连接失败
            console.log('断线重连失败',new Date());
            console.log(e);
            this.socketConnected = false;
          }
        };

        //发送格式化的数据
        this._sendFormattedMsg = function (_userKey,_msgType,_content,_callback){        
          try {
            this.socket.send(JSON.stringify({
              type: _msgType,
              userId: _userKey,
              content: _content
            }));
            console.log('275 null')
            _callback && _callback()
          } catch (e) {
            console.log('sendFormattedMsg 消息发送失败',_userKey,_msgType,_content,new Date());
            console.log('278',e);
            _callback && _callback(e)
          }
          
        }
      };

      //挂载到window
      window.OriocSocket = OriocSocket;
    })

    $(function (){
      
      var socketInstance = new window.OriocSocket({
        url: '',
        //暂时面向整个救援web推送
        loginKey: 'RescureWeb',
        //收到消息
        onMsg: function (_content){
          $('#respondDiv').append($('<p>收到消息: ' + _content + '</p>'))
        },
        //通道开启
        onSocketOpen: function (){
          $('#respondDiv').append($('<p>通道开启</p>'))
        },
        //通道关闭
        onSocketClose: function (){
          $('#respondDiv').append($('<p>通道关闭</p>'))
        },
        onLogin: function (){
          $('#respondDiv').append($('<p>已登录</p>'))
        },
        onDisconnect: function (){
          $('#respondDiv').append($('<p>连接断开</p>'))
        }
      })

      socketInstance.init();

      //点击发送按钮
      $('#sendBtn').click(function (){
        var textInput = $('#textInput').val();
        if (!textInput || textInput.trim() == '') {
          return ;
        }
        socketInstance.sendMsg(textInput);
        $('#respondDiv').append($('<p></p>').text('发送:'+textInput));
        $('#textInput').val('');
      })

      //点击清理按钮
      $('#clearBtn').click(function (){
        $('#respondDiv').empty();
      })

      $('#mockBtn').click(function (){
        socketInstance.mockDisconnect();
        $('#respondDiv').append($('<p></p>').text('模拟断开连接'));
      })

      $('#closeBtn').click(function (){
        socketInstance.close();
        $('#respondDiv').append($('<p></p>').text('完整关闭'));
      })

      $('#reConnectBtn').click(function (){
        socketInstance.close();
        socketInstance.init();
        $('#respondDiv').append($('<p></p>').text('重连'));
      })

      
    })

  </script>
</html>
原文地址:https://www.cnblogs.com/bm20131123/p/12836337.html