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事件。当然,在断开之前也可以发送个同样的断连请求,并包含状态码和原因描述。

时间: 2024-10-30 06:10:54

WebSocket(伍) 断开连接的相关文章

websocket client执行socket_write 就断开连接

问题描述 websocket client执行socket_write 就断开连接 php 充当websocket客户端,模拟向服务器端发消息,但是一执行socket_write连接就丢失了. 是因为php是短连接吗?我在服务端有监控发送的消息,没有收到消息. 代码: $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $result = socket_connect($socket, '********', ***); echo $r

websocket-Websocket过一小段时间就会自动断开连接

问题描述 Websocket过一小段时间就会自动断开连接 如题... 连接上了之后,过几分钟就会自动断开.. 在多个浏览器测试过...结果都是这样... 解决方案 websocket需要进行心跳包维持连接,浏览器不会帮你维持,所以隔断时间就断开了,你自己实现的客户端就需要维持这个连接 解决方案二: 有心跳检测机制么?保持心跳,不要一直空闲. 解决方案三: websocket怎么用

qt-使用QT,主机做了一个服务端,局域网中可以连接别人,别人连接自己输入字符就会断开连接

问题描述 使用QT,主机做了一个服务端,局域网中可以连接别人,别人连接自己输入字符就会断开连接 5C cmd下使用telnet也是输入字符就断开连接电脑杀毒软件一直没启动,防火墙全部关闭,端口号10000然后写了个客户端,同样的问题,输入字符断开连接.楼下依次上图 解决方案 解决方案二: 解决方案三: 解决方案四: 解决方案五: 输入字符a就出现了断开连接 下面上代码 解决方案六: chatsever.h #ifndef CHATSEVER_H#define CHATSEVER_H #inclu

PHP 在 Nginx 下主动断开连接 Connection Close 与 ignore

这两天弄个PHP调用 SVN 同步 update 多台服务器更新的程序,为了避免 commit 的时候不会被阻塞卡半天得想个办法只请求触发,而不需要等待程序 update 完成返回结果这样耗时太长,所以研究过了下如何让PHP主动断开连接的方法.搞了一下午,发现很多问题,还好最终还是弄出来了,主要是 Nginx 太坑.. 废话不多说,下面上代码: /** * 主动断开与客户端浏览器的连接 * 如果是 Nginx 服务器需要输出大于等于 fastcgi_buffer_size 缓存的数据才能即时输出

将数据访问页绑定到断开连接的记录集

断开|访问|记录集|数据 Meyyammai SubramanianMicrosoft Corporation 2001 年 4 月 适用于:Microsoft Access 2002 摘要:本文说明如何将数据访问页绑定到断开连接的 ADO 记录集. 目录简介创建使用断开连接的记录集的数据访问页 简介断开连接的记录集是客户端高速缓存中的对象,该对象没有同服务器实时连接.使用断开连接的记录集,ActiveX 数据对象 (ADO) 允许您创建记录集,断开与数据源的连接,使用户可以脱机查看和编辑记录集

断开连接的记录集

断开|记录集     在一本ASP专著中讨论客户端数据,这与服务器端的ASP编程是否矛盾?情况并非如此,因为我们至今尚未碰到只从事服务器端编程的ASP程序员.虽然ASP是一项服务器端技术,但可以想象,编程人员不可能仅仅使用ASP进行编程.从事ASP编程的Web开发人员,仍然需要与客户端数据进行交互.    因此,围绕着ASP构建一个应用程序时必须考虑整个应用程序的情况,这也意味着必须考虑客户端.为了获得一个运行良好.快速响应的应用程序,需要很好地使用客户端数据.    本章将讨论如何在客户端使用

TCP断开连接过程详解

上次我们讲了TCP三次握手建立连接的过程,今天我们结合双方状态的改变来讲讲TCP断开连接的过程:TCP四次挥手. 数据传输结束后,通信的双方都可释放连接.现在A和B都处于ESTABLISHED状态.A的应用程序先向TCP发出连接释放报文段,主动关闭TCP连接.A把连接释放报文段的首部FIN置为1,序号seq=u,它等于前面已传送过的数据的最后一个字节的序号加1.这时A进入FIN-WAIT-1状态,等待B的确认. B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v

密码登录-Win7远程桌面连接,断开连接后,被控端如何自动返回?

问题描述 Win7远程桌面连接,断开连接后,被控端如何自动返回? 使用win7远程桌面(不进行破解,就是win7原本的单用户登录),连接时,被控端会被踢到输入密码的界面.我的问题是,如何实现,当主控端"断开连接"时,被控端"立刻"返回到"桌面"(而不需要输入密码登录回去),这个如何办到呢? 解决方案 你的客户比较无知,你的任务不是他说什么你做什么,你应该关注他的真实需求. 解决方案二: 这个没办法做到,windows有安全限制 解决方案三: 没有

svn-eclipse中的项目与SVN的仓库:断开连接 ------>选择删除SVN信息 ---->yes

问题描述 eclipse中的项目与SVN的仓库:断开连接 ------>选择删除SVN信息 ---->yes eclipse中的项目与SVN的仓库:断开连接 ------>选择删除SVN信息(我没有选择,没勾上) ---->yes 我没有选择,没勾上,但已经点击了yes了,后面我想删除SVN信息,该怎么办? 求解啊 解决方案 http://www.jb51.net/article/29966.htm 解决方案二: 删除项目SVN信息