精华内容
下载资源
问答
  • springboot+websocket双向通信实现消息推送功能 项目中如果需要假如消息推送功能,有时会用到websocket,这是一种长连接方式与服务器进行连接,优点:实时性较高,如果无数据更新时,并不会频繁进行请求,而只要...

    springboot+websocket双向通信实现消息推送功能

    项目中如果需要假如消息推送功能,有时会用到websocket,这是一种长连接方式与服务器进行连接,优点:实时性较高,如果无数据更新时,并不会频繁进行请求,而只要数据进行更新,那么服务器就会想客户端发送请求,而这样的方式是以服务器资源作为代价来保证实时性。
    前端代码

    //webSocket对象
    var websocket = null;
    var userId;
    //避免重复连接
    var lockReconnect = false, tt;
    
    createWebSocket();
    /**
     * webSocket重连
     */
    function reconnect() {
        if (lockReconnect) {
            return;
        }
        lockReconnect = true;
        tt && clearTimeout(tt);
        tt = setTimeout(function () {
            console.log('重连中...');
            lockReconnect = false;
            createWebSocket();
        }, 4000);
    }
    
    /**
     * websocket心跳检测
     */
    var heartCheck = {
        timeout: 3000,
        timeoutObj: null,
        serverTimeoutObj: null,
        reset: function () {
            clearTimeout(this.timeoutObj);
            clearTimeout(this.serverTimeoutObj);
            return this;
        },
        start: function () {
            var self = this;
            this.timeoutObj && clearTimeout(this.timeoutObj);
            this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
            this.timeoutObj = setTimeout(function () {
                //这里发送一个心跳,后端收到后,返回一个心跳消息,
                websocket.send("connect");
                self.serverTimeoutObj = setTimeout(function () {
                
                }, self.timeout)
            }, this.timeout)
        }
    };
    
    function createWebSocket() {
        //判断当前浏览器是否支持WebSocket
        if ('WebSocket' in window) {
    
            var pathName = window.document.location.pathname;
    
            var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
            
           //动态获取websocket服务地址
             var url = "ws://" + window.document.location.host + projectName + "/webSocket/" + userId;
             // 浏览器支持Websocket
             websocket = new WebSocket(url);
    
             //WebSocket连接发生错误的回调方法
             websocket.onerror = function () {
                 reconnect();
             };
    
             //WebSocket连接成功建立的回调方法
             websocket.onopen = function () {
                 //userId是用户的id也可以是token,按需设置,只要是唯一用户标识
                 websocket.send('{"toUserId":"' + userId + '"}')
                 //心跳检测重置
                 heartCheck.reset().start();
             };
    
             //接收到消息的回调方法
             websocket.onmessage = function (event) {
                 //这里的event则是服务器所发送过来的消息
                 console.log('消息内容:'+event);
                 heartCheck.reset().start();
             };
    
             //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
             window.onbeforeunload = function () {
                 closeWebSocket();
             };
    
             //关闭WebSocket连接
             function closeWebSocket() {
                 websocket.close();
             }
    
             //连接关闭的回调方法
             websocket.onclose = function () {
                 heartCheck.reset();//心跳检测
                 reconnect();
             };
        } else {
            console.log("您的浏览器暂不支持webSocket");
        }
    }
    

    后端代码

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import javax.websocket.*;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    @Component
    @ServerEndpoint(value = "/webSocket/{userId}", configurator = MySpringConfigurator.class)
    public class WebSocket {
        /**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
        private static ConcurrentHashMap<String,WebSocket> webSocketMap = new ConcurrentHashMap<>();
        /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
        private Session session;
        /**接收userId*/
        private String userId="";
    
        /**
         * 连接建立成功调用的方法*/
        @OnOpen
        public void onOpen(Session session,@PathParam("userId") String userId) {
            this.session = session;
            this.userId=userId;
            if(webSocketMap.containsKey(userId)){
                webSocketMap.remove(userId);
                webSocketMap.put(userId,this);
            }else{
                webSocketMap.put(userId,this);
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            if(webSocketMap.containsKey(userId)){
                webSocketMap.remove(userId);
            }
        }
        
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息*/
        @OnMessage
        public void onMessage(String message, Session session) {
            //收到消息的内容可以自定义
        }
    
        /**
         * 连接失败调用的方法
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            error.printStackTrace();
        }
        /**
         * 服务器主动推送消息
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
    
        /**
         * 向用户发送自定义消息
         * */
        public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
            if(webSocketMap.containsKey(userId)){
                webSocketMap.get(userId).sendMessage(message);
            }else{
    
            }
        }
    }
    

    这里有个需要注意的地方,就是webSocket在连接一定时间后未收到服务器消息时会自动断开连接,那么则需要假如心跳检测机制。

    展开全文
  • WebSocket双向通信原理初探

    千次阅读 2018-03-20 19:23:05
     双向通信如何实现先介绍下,TCP/IP参考模型 TCP是一个,相对可靠确保信息送达、按照顺序送达的中层信息传输协议,但性能比UDP较差。它负责两端主机建立会话。我们的websocket处于应用层,也是基于TCP实现的。TCP...

    前言

    WebSocket被广泛用于web的实时消息通信系统中。
     
    它实现了浏览器与服务器全双工通信,将会替代基于http的ajax长轮询的拉取消息模式。
     

    双向通信如何实现

    先介绍下,TCP/IP参考模型
     
    TCP是一个,相对可靠确保信息送达、按照顺序送达的中层信息传输协议,但性能比UDP较差。它负责两端主机建立会话。
    我们的websocket处于应用层,也是基于TCP实现的。

    TCP连接

    采用TCP协议,在真正的读写操作之前,server与client之间必须建立一个连接。读写完成后,双方不再需要这个连接时,就可以释放这个连接。

    TCP短连接

    流程:client向server发起TCP连接请求,client向server发送消息,server回应client,然后一次读写就完成了。这时候client会发起close操作,连接关闭。
    短连接的优点是:
    • 管理起来比较简单,连接都是有用的连接,不需要额外的控制手段
    • HTTP1.0就是基于此实现的,他是是无状态的。浏览器和服务器每一次HTTP操作,就建立一次连接,但任务结束就中断连接。

    TCP长连接:

    流程:client向server发起连接,server接受client连接。双方建立连接,Client与server完成一次读写之后,它们之间的连接并不会主动关闭,用心跳保活。后续的读写操作会继续使用这个连接。
     
    WebSocket就是基于TCP连接建立通讯的。
    一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端或Server端中断连接前,不需要客户端和服务端重新发起连接请求。

    WebSocket建立连接

    websocket与http同样建立于tcp传输协议之上,通过tcp传输层进行数据传输。
    我们要使用websocket协议进行通信则首先要建立起websocket连接,这个连接的建立依赖于http。
     
    发起握手:
    每个WebSocket连接都始于一个HTTP请求。
    具体来说,WebSocket协议在第一次握手连接时,通过HTTP协议在传送数据,但是比普通HTTP请求相比多了一些字段。
            GET /chat HTTP/1.1
            Host: server.example.com
            Upgrade: websocket
            Connection: Upgrade
            Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
            Origin: http://example.com
            Sec-WebSocket-Protocol: chat, superchat
            Sec-WebSocket-Version: 13
     
    服务器响应:
    根据特殊的请求头进行了特殊响应,首先101返回码表明本次连接的通信协议经过了转换并成功握手成功建立起了通信。
    connection字段和upgrade字段则表明本次通信协议进行了升级转换,转换的是websocket协议。
    服务器响应头如下
            HTTP/1.1 101 Switching Protocols
            Upgrade: websocket
            Connection: Upgrade
            Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
            Sec-WebSocket-Protocol: chat
     
    建立了websocket连接后,只要客户端和服务器端任意一端不主动断开连接前,通信行为都是在一个持久连接上发起,后续数据与请求都通过帧序列的形式进行传输。

    总结

    HTTP 1.1也支持了长连接(PersistentConnection),在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,但仍然还是无状态的。
    WebSocket设计上天生为HTTP增强通信,将会在即时IM通讯,游戏等领域会得到更广泛的利用
     
    参考:
     
     
     
    展开全文
  • 服务端使用tomcat7.0 + jsp 客户端使用html5 使用websocket,实现客户端和服务端的双向通信
  • 要求: tomcat7以上 ...首先RabbitMQ安装STOMP 插件 我们进入rabbitmq容器,执行下面的命令开启stomp插件 rabbitmq-plugins enable rabbitmq_web_stomp rabbitmq_web_stomp_examples 将当前的容器提交为新的镜像 ...

    要求:

    tomcat7以上

    前端html5

    首先RabbitMQ安装STOMP 插件

    我们进入rabbitmq容器,执行下面的命令开启stomp插件

    rabbitmq-plugins enable rabbitmq_web_stomp rabbitmq_web_stomp_examples

    将当前的容器提交为新的镜像

    docker commit 3989ec68bf3c rabbitmq:stomp

    停止当前的容器

    docker stop 3989ec68bf3c

    根据新的镜像创建同期

    docker run -di --name=changgou_rabbitmq -p 5671:5617 -p 5672:5672 -p 4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 -p 15670:15670 -p 15674:15674 rabbitmq:stomp

    注意这里插件端口是15674

    然后写前端js

    1.下载stomp.min.js(RabbitMQ官网有提供)
    2.js代码

    <html>
    <head>
        <title>RabbitMQ Web STOMP Examples : Echo Server</title>
        <meta charset="UTF-8">
        <script src="js/stomp.min.js"></script>
    </head>
    <script>
        var client = Stomp.client('ws://localhost:15674/ws');
        var on_connect = function(x) {
    //paynotify是交换机,/exchange是固定写法
            id = client.subscribe("/exchange/paynotify", function(d) {
                alert(d.body);
            });
        };
        var on_error =  function() {
            console.log('error');
        };
    //账号  密码  接到消息执行的方法   异常执行方法   路由
        client.connect('guest', 'guest', on_connect, on_error, '/');
    </script>
    </body>
    </html>

    服务端发消息

    @Autowired
        private StringRedisTemplate redisTemplate;
    public void run(){
    //发一个123的消息
    rabbitTemplate.convertAndSend(paynotify,"","123");
    }

    这样浏览器就可以接受服务端的消息了

    扩展

    destination 在 RabbitMQ Web STOM 中进行了相关的定义,根据使用场景的不同,主要有以下 4 种:

    • 1./exchange/<exchangeName>

    对于 SUBCRIBE frame,destination 一般为/exchange/<exchangeName>/[/pattern] 的形式。该 destination 会创建一个唯一的、自动删除的、名为<exchangeName>的 queue,并根据 pattern 将该 queue 绑定到所给的 exchange,实现对该队列的消息订阅。

    对于 SEND frame,destination 一般为/exchange/<exchangeName>/[/routingKey] 的形式。这种情况下消息就会被发送到定义的 exchange 中,并且指定了 routingKey。

    • 2./queue/<queueName>
      对于 SUBCRIBE frame,destination 会定义<queueName>的共享 queue,并且实现对该队列的消息订阅。
      对于 SEND frame,destination 只会在第一次发送消息的时候会定义<queueName>的共享 queue。该消息会被发送到默认的 exchange 中,routingKey 即为<queueName>。
    • 3./amq/queue/<queueName>
      这种情况下无论是 SUBCRIBE frame 还是 SEND frame 都不会产生 queue。但如果该 queue 不存在,SUBCRIBE frame 会报错。
      对于 SUBCRIBE frame,destination 会实现对队列<queueName>的消息订阅。
      对于 SEND frame,消息会通过默认的 exhcange 直接被发送到队列<queueName>中。
    • 4./topic/<topicName>
      对于 SUBCRIBE frame,destination 创建出自动删除的、非持久的 queue 并根据 routingkey 为<topicName>绑定到 amq.topic exchange 上,同时实现对该 queue 的订阅。
      对于 SEND frame,消息会被发送到 amq.topic exchange 中,routingKey 为<topicName>。
    展开全文
  • 技术栈: vue2.0 + node + websocket( socket.io ) 1. 安装依赖 初始化vue项目后输入下方指令安装依赖包 // 推荐cnpm安装 npm i vue-socket.io -S // for 客户端 npm i socket.io -S // for 服务端node 2....

    技术栈: vue2.0 + node + websocket( socket.io )

    1. 安装依赖

    初始化vue项目后输入下方指令安装依赖包

    // 推荐cnpm安装
    npm i vue-socket.io -S  // for 客户端
    npm i socket.io -S  // for 服务端node

    2. 新建服务端目录如下图  server / app.js 

     

    //  app.js
    var app = require('http').createServer();
    var io = require('socket.io')(app);
    var PORT = 8081;
    
    app.listen(PORT);
    /*
        *新手必读
        *function中的socket为每个客户端单独连接的socket实例,只通知当前连接用户
        *io.sockets 通知所有连接用户
        *socket.broadcast 给除了自己以外的客户端广播消息
    */
    io.on('connection', function (socket) {
        for(let i=0; i<100; i++){
            setTimeout(()=>{
                io.sockets.emit('progress',i);
                console.log("当前进度为",i+1);
            },300*i)
        }
    })
    
    console.log('app listen at:'+PORT);

    一般而言,运行node程序只需要在文件当前目录下命令行输入 node filename 即可,但是,既然是和vue脚手架一起构建,就充分利用起来。

    打开package.json , 在 scripts 中 添加一行

    "server": "node server/app.js",

    现在,直接在vue项目的根目录运行 npm run server 命令就可以开启服务了。

    3.  为了简便,直接修改vue初始化项目中的components下的HelloWorld.vue文件

    // HelloWorld.vue文件
    
    <template>
      <div class="process" >
        <progress max="100" :value="progressValue"></progress>
      </div>
    </template>
    <script>
      import Vue from 'vue'
      import VueSocketio from 'vue-socket.io'
      Vue.use(VueSocketio, 'ws://localhost:8081') // 注意和本地服务器地址及端口一致
    
      export default {
        data(){
          return{
            progressValue: 0, // 进度值
          }
        },
        //(socket.on)绑定事件放在sockets中
        sockets:{ 
          // 创建连接
          connect(){
              console.log('连接成功啦')
          },
          // 监听自定义progress事件,需与服务端emit事件名一致
          progress(res){
            this.progressValue = res;
            console.log('2222',res)
          }
        }
      }
    </script>
    <style scoped>
      .process { text-align:center; }
    </style>

    最后,运行代码

    npm run server   // 开启服务

    切记,不要关闭窗口,然后再新开命令行,注意,是新开一个,运行

    npm run dev

    就能看到一个进度条的效果了( 客户端(浏览器)发起请求,然后服务端不停传输数据,客户端监听对应事件和数据并重新渲染页面 )。

    这只是很简单的一个应用,在此基础上很容易就可以改成比较多人在线聊天室的功能。

     

    转载于:https://www.cnblogs.com/hcxy/p/8575208.html

    展开全文
  • 会展示一个,个人理解的WebSocket最简单的用法。 重点 1、JAVA内的WebSocket是在Java jar7.0之后才能使用的。 2、需要在JavaServer项目lib目录下引入 javaee-api-7.0 包 |前端代码...
  • 下面记一下一个简单的基于GatewayWorker框架写的websocket的程序。 传统的websocket使用方式都是 1.客户端像服务器发送http请求,并发起websocket链接请求。 然后php框架调用GatewayWorker进行uid和websock...
  • Websocket实现双向通信

    2012-07-08 13:40:00
     socket=new WebSocket(url);  socket.onopen=function(event){  log("连接已建立"+this.readyState);  };  socket.onmessage=function(event){  log("接收到的数据:"+event.data+"</b>");  };  socket.on...
  • 前言众所周知,PHP用于开发基于HTTP协议的网站应用非常便捷。...即使采用客户端主动轮询的方式来间接实现双向通信,也会较大地增加服务器的负担,增大代码的复杂性,不利于维护。那么,是否PHP就无法用来开发双向...
  • 前言众所周知,PHP用于开发基于HTTP协议的网站应用非常便捷。...即使采用客户端主动轮询的方式来间接实现双向通信,也会较大地增加服务器的负担,增大代码的复杂性,不利于维护。双向通信那么,是否PHP就无法用来...
  • 将注册表及服务中的残存数据(jvm)删除干净——CCleaner(完美清除) ... 安装 (其他博主的内容) 改进文章订阅功能,创建RabbitMQ队列存放新消息通知、改进发布文章后群发消息...整合Netty和WebSocket实现双向通信 do...
  • 前言 众所周知,PHP用于开发基于HTTP协议的网站应用非常便捷。...即使采用客户端主动轮询的方式来间接实现双向通信,也会较大地增加服务器的负担,增大代码的复杂性,不利于维护。 那么,是否PHP就无法用来开发...
  • 双向通信websocket

    2019-05-07 08:49:19
    简介 定义一个API,用以在网页浏览器和服务器之间建立socket连接,这个...支持双向通信,实时性强 更好的二进制支持 没有同源限制,客户端可以与任意服务器通信 较少的控制开销(创建后,ws客户端\服务端进行数据交换时,...
  • websocket即时通信 php

    2018-03-10 22:26:21
    websocket实现了服务器与客户端的双向通信,即使客户端没有请求,服务器端也可以主动发送消息。部分主要代码如下:public function run(){ $this-&gt;service(); //开启websocket函数 $clients[] = $this-&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,358
精华内容 543
关键字:

websocket双向通信