WebSocket(伍) 断开连接

原文链接 https://www.web-tinker.com/article/20310.html


WebSocket是很民主的,啥都要协商!建立连接时需要握手协议,连断开连接都需要双方共同完成!其实断开连接直接断开TCP连接就可以了,但是这有点暴力。文明点的方法是发个请求,让对方自己断开。客户端要主动断开就必须向服务器发送8这个操作码。
  首先是服务器主导断开的情况,最简单的方法是直接把TCP连接断开,这里就不演示了。由于这对客户端来说是个意外断开,WebSocket对象采取应急措施也触发close事件。咱是文明人,当然要做点有绅士风度的事情。于是咱不从服务器断开连接,而是向客户端发送个请求断开的操作码来请求客户端自己断开。
  其实就是个操作码为8的帧。但要注意的是数据部分比较特殊。当然如果嫌麻烦可以不传,不过要是不传就和前面的霸王硬上弓一样无节操了。数据部分的前两个字节是状态码,之后的部分是关闭连接原因的文本描述,这些东西可以传到客户端。
  (encodeDataFrame与decodeDataFrame函数见生成数据帧和解析数据帧)

//客户端程序
var ws=new WebSocket("ws://127.0.0.1:8000");
ws.onclose=function(e){
  console.log(e);
  ws.close(); //关闭TCP连接
};

========================================================

//服务器程序
var crypto=require('crypto');
var WS='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
require('net').createServer(function(o){
  var key;
  o.on('data',function(e){
    if(!key){
      //握手
      key=e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
      key=crypto.createHash('sha1').update(key+WS).digest('base64');
      o.write('HTTP/1.1 101 Switching Protocols\r\n');
      o.write('Upgrade: websocket\r\n');
      o.write('Connection: Upgrade\r\n');
      o.write('Sec-WebSocket-Accept: '+key+'\r\n');
      o.write('\r\n');
      //构造断连请求的数据部分,前面留两字节存放状态码
      var buf=new Buffer('\0\0孩子,地球太危险了,快回火星去吧!');
      buf.writeUInt16BE(1000,0); //在头两个字节写入一个状态码
      //发送断连请求
      o.write(encodeDataFrame({FIN:1,Opcode:8,PayloadData:buf}));
    };
  });
}).listen(8000);


客户端会在onclose的参数中接收到一个这样的东西,状态码和结束原因描述分别在code和reason两个参数中。规范文档中规定了很多状态码的含义,不过这个目前不是强制性的,我就不列举了。见RFC6455#section-7.4。客户端在收到服务器的这个断连请求后应该调用close方法来关闭,否则连接会先入停滞状态等待客户端响应。
  服务器主导断开的情况就是这样。下面是客户端主导断开的情况。客户端先要调用close方法,这个操作会发送一个断连请求到服务器上,服务器收到这个请求后把TCP连接断开即可。但是服务器程序是自己写的,这个请求也需要自己解析。

//客户端程序
var ws=new WebSocket("ws://127.0.0.1:8000");
ws.onopen=function(){
  ws.close(); //发起断连请求
};
ws.onclose=function(e){
  console.log(e);
};

//服务端程序序
var crypto=require('crypto');
var WS='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
require('net').createServer(function(o){
  var key;
  o.on('data',function(e){
    if(!key){
      //握手
      key=e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];
      key=crypto.createHash('sha1').update(key+WS).digest('base64');
      o.write('HTTP/1.1 101 Switching Protocols\r\n');
      o.write('Upgrade: websocket\r\n');
      o.write('Connection: Upgrade\r\n');
      o.write('Sec-WebSocket-Accept: '+key+'\r\n');
      o.write('\r\n');
    }else{
      var frame=decodeDataFrame(e);
      console.log(frame);
      if(frame.Opcode==8){
        //这里也可以发送个结束包来给客户端的onclose中带参数
        //var buf=new Buffer('\0\0孩子,地球太危险了,快回火星去吧!');
        //buf.writeUInt16BE(1000,0);
        //o.write(encodeDataFrame({FIN:1,Opcode:8,PayloadData:buf}));
        o.end(); //断开连接
      };
    };
  });
}).listen(8000);



总之,客户端直接调用close方法并不会关闭连接,而是发送请求到服务器请求对方。服务器接收请求后可以断开连接。这会触发客户端的close事件。当然,在断开之前也可以发送个同样的断连请求,并包含状态码和原因描述。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WebSocket并不总是断开连接WebSocket的连接状态取决于多种因素,包括网络环境、服务器配置以及客户端代码等。当出现某些情况时,WebSocket可能会断开连接。以下是一些可能导致WebSocket断开连接的常见原因: 1. 网络问题:如果客户端或服务器之间的网络连接不稳定,或者网络中存在阻止WebSocket连接的防火墙或代理服务器,可能会导致WebSocket断开连接。 2. 服务器问题:如果服务器端出现故障、重启或关闭,或者服务器端的WebSocket服务不可用,也会导致WebSocket断开连接。 3. 客户端问题:如果客户端的代码实现有错误、逻辑问题或内存泄漏,也可能导致WebSocket断开连接。 4. 协议问题:如果WebSocket协议版本不匹配、握手失败或发生其他协议相关的问题,也可能导致WebSocket断开连接。 为了更好地排查WebSocket连接断开的原因,您可以在WebSocket的onclose事件处理程序中打印错误信息。根据您提供的代码示例,您可以在断开连接时打印出错误信息,包括错误码、原因和断开状态等。这样可以帮助您更好地理解为什么WebSocket连接断开。 请注意,您提到了在浏览器中运行WebSocket聊天室的问题。如果您遇到了连接问题,可能是由于您在浏览器中的代码实现有问题,或者受到浏览器的安全策略限制。建议您检查您的代码实现并确保它符合WebSocket的规范和要求。您可以参考WebSocket相关的文档和示例来获取更多的帮助和指导。 总结来说,WebSocket连接断开的原因可能涉及网络问题、服务器问题、客户端问题和协议问题。通过打印错误信息和检查代码实现,您可以更好地了解和解决WebSocket连接断开的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值