精华内容
下载资源
问答
  • websocket怎么断开连接
    2021-09-06 00:12:55

    最近从在写一个课程上报的模块,要求前端使用websocket长连接到后端,实现实时上报学习进度的功能。这次没有使用php或者java,尝试使用一把golang作为上报模块的开发语言。用到了gorm和websocket,这次总结下遇到的坑。

    1.websocket无法检测到连接断开

    在使用websocket的时候,因为其底层基于tcp连接,所以不执行发送命令是获取不到连接断开的通知的;因此前端发送心跳包到后端,后端可以以返回一个心跳包的形式,判断是否出现err,如果出现err则说明连接断开,处理断开后的逻辑,保存进度等操作。

    2.gorm导致的504问题

    从百度和google搜到的全部都是因为Quer导致的rows没有close的问题,还有说使用gorm的db.Close解决,但我们都没解决。用navicat->工具->服务器监控发现数据库里建立了大量的链接。
    最后发现是程序处理心跳的协程使用for死循环,使用了事务,但是open没有执行rollback或者commit,直接continue了,continue之后又会执行一个新的事务begin。加上rollback就解决了

    更多相关内容
  • WebSocket断开连接

    千次阅读 2020-12-18 17:57:27
    建立连接时需要握手协议,连断开连接都需要双方共同完成!其实断开连接直接断开TCP连接就可以了,但是这有点暴力。文明点的方法是发个请求,让对方自己断开。客户端要主动断开就必须向服务器发送8这个操作码。首先是...

    WebSocket是很民主的,啥都要协商!建立连接时需要握手协议,连断开连接都需要双方共同完成!其实断开连接直接断开TCP连接就可以了,但是这有点暴力。文明点的方法是发个请求,让对方自己断开。客户端要主动断开就必须向服务器发送8这个操作码。

    首先是服务器主导断开的情况,最简单的方法是直接把TCP连接断开,这里就不演示了。由于这对客户端来说是个意外断开,WebSocket对象采取应急措施也触发close事件。咱是文明人,当然要做点有绅士风度的事情。于是咱不从服务器断开连接,而是向客户端发送个请求断开的操作码来请求客户端自己断开。

    其实就是个操作码为8的帧。但要注意的是数据部分比较特殊。当然如果嫌麻烦可以不传,不过要是不传就和前面的霸王硬上弓一样无节操了。数据部分的前两个字节是状态码,之后的部分是关闭连接原因的文本描述,这些东西可以传到客户端。

    (encodeDataFrame与decodeDataFrame函数见生成数据帧和解析数据帧)

    1 //客户端程序

    2 var ws=new WebSocket("ws://127.0.0.1:8000");3 ws.onclose=function(e){4 console.log(e);5 ws.close(); //关闭TCP连接

    6 };

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

    1 //服务器程序

    2 var crypto=require('crypto');3 var WS='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';4 require('net').createServer(function(o){5 varkey;6 o.on('data',function(e){7 if(!key){8 //握手

    9 key=e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];10 key=crypto.createHash('sha1').update(key+WS).digest('base64');11 o.write('HTTP/1.1 101 Switching Protocols\r\n');12 o.write('Upgrade: websocket\r\n');13 o.write('Connection: Upgrade\r\n');14 o.write('Sec-WebSocket-Accept: '+key+'\r\n');15 o.write('\r\n');16 //构造断连请求的数据部分,前面留两字节存放状态码

    17 var buf=new Buffer('\0\0孩子,地球太危险了,快回火星去吧!');18 buf.writeUInt16BE(1000,0); //在头两个字节写入一个状态码

    19 //发送断连请求

    20 o.write(encodeDataFrame({FIN:1,Opcode:8,PayloadData:buf}));21 };22 });23 }).listen(8000);

    客户端会在onclose的参数中接收到一个这样的东西,状态码和结束原因描述分别在code和reason两个参数中。规范文档中规定了很多状态码的含义,不过这个目前不是强制性的,我就不列举了。见RFC6455#section-7.4。客户端在收到服务器的这个断连请求后应该调用close方法来关闭,否则连接会先入停滞状态等待客户端响应。

    服务器主导断开的情况就是这样。下面是客户端主导断开的情况。客户端先要调用close方法,这个操作会发送一个断连请求到服务器上,服务器收到这个请求后把TCP连接断开即可。但是服务器程序是自己写的,这个请求也需要自己解析。

    1 //客户端程序

    2 var ws=new WebSocket("ws://127.0.0.1:8000");3 ws.onopen=function(){4 ws.close(); //发起断连请求

    5 };6 ws.onclose=function(e){7 console.log(e);8 };

    1 //服务端程序序

    2 var crypto=require('crypto');3 var WS='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';4 require('net').createServer(function(o){5 varkey;6 o.on('data',function(e){7 if(!key){8 //握手

    9 key=e.toString().match(/Sec-WebSocket-Key: (.+)/)[1];10 key=crypto.createHash('sha1').update(key+WS).digest('base64');11 o.write('HTTP/1.1 101 Switching Protocols\r\n');12 o.write('Upgrade: websocket\r\n');13 o.write('Connection: Upgrade\r\n');14 o.write('Sec-WebSocket-Accept: '+key+'\r\n');15 o.write('\r\n');16 }else{17 var frame=decodeDataFrame(e);18 console.log(frame);19 if(frame.Opcode==8){20 //这里也可以发送个结束包来给客户端的onclose中带参数

    21 //var buf=new Buffer('\0\0孩子,地球太危险了,快回火星去吧!');

    22 //buf.writeUInt16BE(1000,0);

    23 //o.write(encodeDataFrame({FIN:1,Opcode:8,PayloadData:buf}));

    24 o.end(); //断开连接

    25 };26 };27 });28 }).listen(8000);

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

    展开全文
  • websocket断开连接 代码解析

    千次阅读 2020-02-24 14:37:50
    WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。 ws.onclose = function (e) { console.log('websocket 断开: ’ + e.code + ’ ’ + e.reason + ’ ’ + e.wasClean) console.log(e) } 错误...

    WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。
    ws.onclose = function (e) {
    console.log('websocket 断开: ’ + e.code + ’ ’ + e.reason + ’ ’ + e.wasClean)
    console.log(e)
    }
    错误状态码:

    WebSocket断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WebSockets 的客户端. 它在 WebSocket 对象的 onclose 事件监听器中使用。CloseEvent的code字段表示了WebSocket断开的原因。可以从该字段中分析断开的原因。

    CloseEvent有三个字段需要注意, 通过分析这三个字段,一般就可以找到断开原因

    CloseEvent.code: code是错误码,是整数类型
    CloseEvent.reason: reason是断开原因,是字符串
    CloseEvent.wasClean: wasClean表示是否正常断开,是布尔值。一般异常断开时,该值为false
    状态码 名称 描述
    0–999 保留段, 未使用.
    1000 CLOSE_NORMAL 正常关闭; 无论为何目的而创建, 该链接都已成功完成任务.
    1001 CLOSE_GOING_AWAY 终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开.
    1002 CLOSE_PROTOCOL_ERROR 由于协议错误而中断连接.
    1003 CLOSE_UNSUPPORTED 由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据).
    1004 保留. 其意义可能会在未来定义.
    1005 CLOSE_NO_STATUS 保留. 表示没有收到预期的状态码.
    1006 CLOSE_ABNORMAL 保留. 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧).
    1007 Unsupported Data 由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据).
    1008 Policy Violation 由于收到不符合约定的数据而断开连接. 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景.
    1009 CLOSE_TOO_LARGE 由于收到过大的数据帧而断开连接.
    1010 Missing Extension 客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接.
    1011 Internal Error 客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接.
    1012 Service Restart 服务器由于重启而断开连接.
    1013 Try Again Later 服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接.
    1014 由 WebSocket标准保留以便未来使用.
    1015 TLS Handshake 保留. 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书).
    1016–1999 由 WebSocket标准保留以便未来使用.
    2000–2999 由 WebSocket拓展保留使用.
    3000–3999 可以由库或框架使用.? 不应由应用使用. 可以在 IANA 注册, 先到先得.
    4000–4999 可以由应用使用.

    END

    展开全文
  • Vue作为一个单页面应用, webSocket可以说是用起来非常爽了. 因为webSocket在同一个html文件中,是...先说下我踩过的坑,起初我设想,在登录并创建websocket连接成功后,设置一个字段保存在localStorage或者cookie中: w...

    Vue作为一个单页面应用, webSocket可以说是用起来非常爽了. 因为webSocket在同一个html文件中,是可以保持连接的. 但是当使用f5或者点击刷新页面以后, websocket连接就会强制关闭. 关于这个问题我研究了很久,最后找到两种解决办法;

    先说下我踩过的坑,起初我设想,在登录并创建websocket连接成功后,设置一个字段保存在localStorage或者cookie: window.localStorage.setItem(‘connSocket’,’1’), 在关闭时触发window.localStorage.setItem(‘connSocket’,’0’),然后在vue的全局路由中进行判断, 每次路由发生变化时,如果已登录但connSocket值为0,则创建socket连接,否则不处理;

    设想很美好, 然而实际操作过程中, 发现页面手动f5或按钮刷新时, 根本不触发websocketonclose事件, 因为此时连接并不是正常关闭的.....这个设想流产了, 但是启发了我第一个解决办法的思路. 后面再提;

    我踩过的第二个坑, 是在网上百度到, js通过监控页面刷新事件, 可以进行一些操作,示例代码如下:

    window.onbeforeunload = function(event) {
    	console.log('您正在刷新网页');
    	return 'Are you sure?';
    };

    当我把这段代码放到vue挂载的html中之后, 结果页面刷新根本不触发这个事件. 因此我转而研究vue的生命周期,尝试在destroyed的钩子函数中,设置localStorageconnSocket的值,没错,此时我仍旧是想通过这种方法来控制路由判断. 测试半天发现在这个钩子函数中并不能操作localStorage这个对象. 而且页面刷新时, 似乎并不会触发这个钩子函数, 反而每一次刷新,createdmounted函数是一定会被触发的. 于是我决定在created中操作localStorage. 终于生效了, 我成功删除了. 这个思路又启发了第二个解决办法的诞生, 并且比第一种简单许多许多. 接下来,就贴下两种解决方案的代码.

    首先, 准备工作, 先封装一个连接websocket的函数:

    //创建websocket连接
      connectSocket(host) {
        window.webSocket = new WebSocket(host);
        /*建立连接*/
        webSocket.onopen = evt => {
          console.log("webSocket连接成功");
          let data = {type: 'bind'};
          let json = JSON.stringify(data);
          webSocket.send(json);
        };
        /*连接关闭*/
        webSocket.onclose = evt => {
          console.log("webSocket连接关闭");
        };
        /*接收服务器推送消息*/
        webSocket.onmessage = evt => {
          let data = JSON.parse(evt.data);
          console.log(data)
        };
        /*连接发生错误时*/
        webSocket.onerror = (evt,e) => {
          console.log(evt);
        }
      }

    封装好之后, 在main.js中把这个函数注册全局, 我是在我的项目中封装了一个包裹所有的全局函数的global.js文件,注入在了vue实例中. 如果只注入现在这个连接函数的话,参考下列代码:

    Vue.prototype.$connectSocket= (上面贴的那个函数内容);

    接下来说第一种解决方案:

    在通过监听socket关闭事件时尝试修改localStorage值失败之后,我气得关上电脑去洗澡, 睡衣还没拿好我就突然想到了vuex, 之前一直苦恼vuex中存储的值在页面刷新后都被重置为默认值, 才想到把数据存储在localStorage中的结局方案. 此时我为何要绕远路把标记websocket连接的状态值存储在localStorage中呢,我为什么不存在vuex中呢.........想到这里就豁然开朗了,开始在全局路由拦截中进行判断.

    /*登录状态下,判断是否存在websocket连接是否存在,不存在则立即建立连接*/
    const listenSocket = ()=>{
      let userMessage = JSON.parse(window.localStorage.getItem('userMessage'));
      let token = userMessage ? userMessage.token : '';
      let socketState = store.state.socketConnect;
      if(token && !socketState){
        console.log(socketState);
        console.log('用户是登录状态,但并未创建socket连接')
        global.connectSocket('你的webSocket连接地址');
      }
    }
    
    /*全局路由控制*/
    router.beforeEach((to, from, next) => {
      /* 路由发生变化修改页面title */
      if (to.meta.title) {
        document.title = to.meta.title
      }
      listenSocket();   //这调用了判断socket是否连接的函数, 在每一次路由变化时都会调用
    
      next()
      /*路由验证拦截*/
      //routerIntercept(to, from, next);
    });

    在这里我用localStorage中的值判断是否登录. 用vuex中的socketConnect判断是否创建连接. 在登录成功后,将socketConnect=true, 在页面刷新后socketConnect自动置为默认值false; 此时就会调用connectSocket()创建连接了; 如果正常的页面内路由跳转, 并没有刷新页面. 则socketConnect一直都是true, 不会重新创建socket连接了. 

    总的来说第一种方法比较笨重,牵扯的对象比较多,有vuex, localStorage, 相对来说第二种方法就要简单许多许多了;

    第二种方法, 前面说到刷新页面时,组件的created和mounted钩子函数是一定会被调用的, 因此我们可以在vue项目的根组件上,加一段代码, 我的项目是vue-cli生成的,因此根组件是app.vue;在这个app.vue中加入如下代码:

    export default {
      name: 'App',
      created() {
        //当在任一路由页面被刷新时,即是根组件app被重新创建,此时可以进行webSocket重连
        //从localStorage中获取用户信息,是登录状态则可以进行webSocket重连
        let userMessage = window.localStorage.getItem('userMessage');
        if(userMessage){
          userMessage = JSON.parse(userMessage);
          this.$globalFunction.connectSocket('你的webSocket连接地址');
        }
      }
    }

    这里不需要用到vuex, 原理也很简单, 正常登录后创建的websocket连接会一直保持. 用户刷新页面后, 则是根组件被重新创建, 此时在钩子函数created中判断用户是否登录, 登录状态则创建socket连接, 否则不做任何处理.

    这里还需要注意的一点是, 用户在手动退出登录之后, 应该关闭socket连接. 为了方便, 我在封装connectSocket函数时,创建websocket对象使用如下代码:

    window.webSocket = new WebSocket(host);

    也就是把创建的这个webSocket对象注册到window对象下, 这样我在站内的任何地方都可以很方便的调用这个websocket对象了, 退出登录时,只需调用如下方法:

    webSocket.close();
    总结的差不多啦~~我觉得大脑可以歇一歇了
    展开全文
  • 问题:由于 web session 超时时间为 30 分钟,如用户在 web session 规定时间内没有退出系统,但由于其它原因 用户却断开websocket连接,如果用户还要聊天或是其它 websocket 方面的操作,那么就只能重新连接...
  • 1、断开原因 WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。 ws.onclose = function ...WebSocket断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WebSockets 的客户端. 它在
  • spring websocket自动断开连接再创建引发的问题解决方案
  • I have a nodejs websocket server and I have the following problem.When my clients connect to the server and terminate gracefully the onclose method is called on those sockets and I perform clean up op...
  • 1. 把错误打印出来WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。ws.onclose = function (e) {console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean)console.log(e)...
  • https://blog.svenhetin.com/chu-tan-he-shi-xian-websocketxin-tiao-zhong-lian/https://www.crifan.com/websocket_ping_pong_best_interval_time/https://www.oschina.net/question/137225_27929心跳重连缘由...
  • 1、断开原因 WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。 ws.onclose = function ...WebSocket断开时,会触发CloseEvent, CloseEvent会在连接关闭时发送给使用 WebSockets 的客户端. 它在
  • 我设法使用Spring 5 ...但是,我不知道如何检测客户端断开连接.调试客户端断开连接时,它会在HttpServerWSOperations类(netty.http.server包)的服务器端停止,并在其中检测到CloseWebSocketFrame.任何建议如何处...
  • WebSocket断开原因

    千次阅读 2019-11-09 01:09:55
    1、WebSocket断开的原因有很多,最好在WebSocket断开时,将错误打印出来。 ws.onclose = function (e) { console.log('websocket 断开: ' + e.code + ' ' + e.reason + ' ' + e.wasClean) console.log(e) } 2、...
  • 先看我的WebSocket服务器端代码: socket.on('disconnect', function(){ console.log("disconnect event detected, client is probably not there"...一旦客户端比如浏览器主动断开连接,服务器...
  • 在上面集成Websocket实现消息推送的基础上。除给web端页面进行推送数据,还需要给Android端推送数据。在特殊的业务场景下,Android会经常性断网和关机,SpringBoot后台jar包部署在Windows服务器上。当终端过多且累计...
  • 我试图让WebSocket在发生故障时重新连接public class WebSocketClient extends WebSocketListener {volatile OkHttpClient client;volatile WebSocket webSocket;volatile Boolean isConnected = false;public ...
  • java websocket断开重连

    千次阅读 2018-11-04 11:29:09
    #java websocket断开重连,java客户端websocket断开重连 最近一个需求。需要用java客户端的方式连接远程的webscoket 站点。需要保证连接断开自动重连,于是基于Java-WebSocket这个开源代码实现了断开重连,代码比较...
  • 客户端连接websocket,握手正常,服务端和客户端正常交互,停一会就客户端就会出现 WebSocketBase::onCloseWrapper code : 1009 reason: The decoded text message was too big for the output...
  • websocket 断开重连

    万次阅读 2018-08-02 17:33:30
    websocket 5行代码模子: 1.实例化WebSocket对象  var old=new WebSocket("ws://xxx.xxxxx.xxx.xxxx"); 2.回调事件的处理  old.onerror = function(){}  old.onopen = function(){}  old.onmessage=...
  • WebSocket(伍) 断开连接

    万次阅读 2017-02-20 09:59:28
    建立连接时需要握手协议,连断开连接都需要双方共同完成!其实断开连接直接断开TCP连接就可以了,但是这有点暴力。文明点的方法是发个请求,让对方自己断开。客户端要主动断开就必须向服务器发送8这个操作码。  ...
  • WebSocket客户端和服务器断开连接后,服务器捕捉到连接中断事件,需要析构掉服务器端为这个客户端连接维护的一些数据结构,以释放资源。 其中一个待释放的资源就是oTransactionID_SiteDetailMap 比如这个字段就...
  • 重新连接WebSocket是一个基于的websocket客户端,如果断开连接,它将自动重新连接-线程安全! 安装 go get github.com/recws-org/recws 赞助商 商标 徽标由 地鼠通过 执照 recws是根据的开源软件。
  • 笔记 项目结构 代码 @Slf4j @Component @ServerEndpoint("/echo/{sid}") ... * concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象 */ private static CopyOnWrite...
  • 关于websocket断开连接的一些猜想

    千次阅读 2015-09-16 00:03:25
    前段时间由于工作需要,自己使用websocket编写了一个简单的IM功能,刚开始测试时,简单的测试了功能,都可以满足要求,后来发现通信不是很稳定。 后来专门花时间测试,最终发现是服务器那边对连接有个默认超时释放的...
  • 记一次websocket的自动断开连接

    千次阅读 2019-03-14 01:29:46
    websocket与后台连接用着用着就自动断开了: 原因分析: 1.首先再websocket的关闭回调中添加日志,观察输出日志 ws.onclose = function (e) { console.log('websocket 断开:' + e.code + ' ' + e.reason + ' ' +...
  • 如果存在服务器主动断开与客户端连接的websocket的情况, 服务器端或者客户端应该如何写才能让客户端接收到连接被断开连接的反馈? 麻烦定时检测是否断开的这种方法就不要说了。
  • websocket收发数据(定向+广播)的简单实现和实战案例

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,415
精华内容 7,766
关键字:

websocket怎么断开连接