精华内容
下载资源
问答
  • WebSocket

    2020-08-27 19:32:06
    我上次大量图片和的xml文件,并保存表单入库,涉及到一个解析xml文件信息入库的问题,因为文件很多,解析的速度比较,不能让页面停留,所以采用的是websocket推送,当时使用的项目是springboot-shiro管理的,采用...

    WebSocket消息推送


    我这边使用到的场景:

    我上次大量图片和的xml文件,并保存表单入库,涉及到一个解析xml文件信息入库的问题,因为文件很多,解析的速度比较慢,不能让页面停留,所以采用的是websocket推送,当时使用的项目是springboot-shiro管理的,采用的还是shiro管理的session会话,没有使用到无状态登录,后面把项目改成了无状态登录,在该之前就把websoket功能去除了,所以还没尝试怎么修改无状态的消息推送

    废话不多说,上代码

    后台代码

    先写一个配置类

    package com.sample.config.pubic;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    
    /**
     *@ClassName WebSocketConfig
     *@Description WebSocket配置类
     *@Author huangzq
     *@Date 2020/5/30 11:35
     *@Version 1.0
     */
    
    /**
     * 开启WebSocket支持
     */
    @Configuration
    public class WebSocketConfig {
    
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    }
    
    

    处理的业务层

    package com.sample.controller.sample;
    
    import com.sample.service.sample.TbXmlService;
    import com.sample.utils.StaticFinalDataClass;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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.File;
    import java.io.IOException;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.CopyOnWriteArraySet;
    
    import static com.sample.utils.ThumbUtils.delAllFile;
    
    /**
     * @ClassName WebSocketServer
     * @Description webSocketServer服务端类
     * @Author huangzq
     * @Date 2020/5/30 11:36
     * @Version 1.0
     */
    
    @ServerEndpoint("/websocket/{sid}")
    @Component
    public class WebSocketServer {
        private static Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
    
        @Autowired
        private TbXmlService tbXmlService;
    
        /**
         * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
         */
        private static int onlineCount = 0;
        /**
         * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
         */
        private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
    
        /**
         * 与某个客户端的连接会话,需要通过它来给客户端发送数据。
         */
        private Session session;
    
        /**
         * 接收sid
         */
        private String sid = "";
    
    
        /**
         * 连接建立成功调用的方法
         */
        @OnOpen
        public void onOpen(Session session, @PathParam("sid") String sid) {
            this.session = session;
            webSocketSet.add(this);
            addOnlineCount();
            logger.info("有新窗口开始监听:" + sid + ",当前在线人数为" + getOnlineCount());
            this.sid = sid;
            try {
                sendMessage("正在解析xml!");
            } catch (IOException e) {
                logger.error("websocket IO异常");
            }
        }
    
        /**
         * 连接关闭调用的方法
         */
        @OnClose
        public void onClose() {
            webSocketSet.remove(this);
            subOnlineCount();
            logger.info("有一连接关闭!当前在线人数为" + getOnlineCount());
        }
    
        /**
         * 收到客户端消息后调用的方法
         *
         * @param message 客户端发送过来的消息
         */
        @OnMessage
        public void onMessage(String message, Session session) {
            logger.info("收到来自窗口" + sid + "的信息:" + message);
            //群发消息
            for (WebSocketServer item : webSocketSet) {
                try {
                    item.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * @param session
         * @param error
         */
        @OnError
        public void onError(Session session, Throwable error) {
            logger.error("发生错误");
            error.printStackTrace();
        }
    
    
        /**
         * @author huangzq
         * @description 实现服务器主动推送
         * @date 2020/6/1 14:26
         * @Param [message]
         * @Return void
         */
        public void sendMessage(String message) throws IOException {
            this.session.getBasicRemote().sendText(message);
        }
    
    
        /**
         * @author huangzq
         * @description 对xml数据进行解析处理   暂时闲置
         * @date 2020/6/1 14:25
         * @Param [message]
         * @Return void
         */
        public void sendInfo(List<Map<String, String>> imgInfo) throws IOException {
            for (WebSocketServer item : webSocketSet) {
                try {
                    //开启数据校验,校验成功并插入数据库
    //                tbXmlService.handleXml(imgInfo);
                    //解析完成后删除临时存放xml文件的文件夹
                    delAllFile(new File(StaticFinalDataClass.XML_FILE_LINSHI_PATH));
                    item.sendMessage("解析完成!");
                } catch (IOException e) {
                    continue;
                }
            }
        }
    
        public static synchronized int getOnlineCount() {
            return onlineCount;
        }
    
        public static synchronized void addOnlineCount() {
            WebSocketServer.onlineCount++;
        }
    
        public static synchronized void subOnlineCount() {
            WebSocketServer.onlineCount--;
        }
    
        public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
            return webSocketSet;
        }
    
    }
    
    

    调用该业务层的方法sendInfo()进行处理,成功后会自动调用onMessage()方法向前台推送消息,登录成功一半是有一个session会话的,这里会自动触发onOpen()方法

    前台代码

    这个写在js中

    var personSample = 2;
    if(typeof(WebSocket) == "undefined") {
        console.log("您的浏览器不支持WebSocket");
    }else{
        // console.log("您的浏览器支持WebSocket");
        //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
        index = new WebSocket(basePaths + "/websocket/"+ personSample);
        //打开事件
        index.onopen = function() {
            //socket.send("这是来自客户端的消息" + location.href + new Date());
        };
        //获得消息事件
        index.onmessage = function(msg) {
            parent.$("#handlexml").html(msg.data);
        };
        //关闭事件
        index.onclose = function() {
            console.log("Socket已关闭");
        };
        //发生了错误事件
        index.onerror = function() {
            // console.log("Socket发生了错误");
        }
    }
    

    这个personSample 值你不需要管,因为这个是我在当前的项目中使用了三个系统,这个值是2表示第二个系统

    jar包

    	<!--集成websocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
    
    展开全文
  • 但打包完部署到linux上运行,Websocket连接特别,平均要花10秒左右才能建立连接。 框架结构 整体采用前后端分离开发: 前端:Vue.js+sockjs-client+Webstomp-client 后端:Springboot+WebStomp 关于前后端...

    问题描述

    系统在本地开发测试时Websocket连接很正常,都是秒连。但打包完部署到linux上运行,Websocket连接特别慢,平均要花10秒左右才能建立连接。

    框架结构

    整体采用前后端分离开发:
    前端:Vue.js+sockjs-client+Webstomp-client
    后端:Springboot+WebStomp

    关于前后端Websocket具体实现,可移步我的另一篇博客:
    前后端分离WebSocket +Springboot 实战详解

    过程

    排除了网络问题之后,在一步步的Debug之中,拨开了Bug的层层面纱。最终发现原来是Java原生方法InetAddress.getLocalHost()的坑~

    在websocket连接过程中,会将http协议升级为websocket协议,在升级过程中,调用了InetAddress.getLocalHost(),而这个方法的底层获取依赖于JDK原生InetAddress类的操作。
    下面是JDK中InetAddress类的描述

    • InetAddress Caching

    • The InetAddress class has a cache to store successful as well as unsuccessful host name resolutions.

    By default, when a security manager is installed, in order to protect against DNS spoofing attacks, the result of positive host name resolutions are cached forever. When a security manager is not installed, the default behavior is to cache entries for a finite (implementation dependent) period of time. The result of unsuccessful host name resolution is cached for a very short period of time (10 seconds) to improve performance.

    为了防止DNS欺骗攻击,这个类会缓存获取主机地址的结果,默认缓存10秒,也就是说如果获取失败了,10秒之内都会处于等待状态,拿不到正确的结果。

    解决方案

    在系统hosts文件中增加本地ip地址与主机名的对应项

    例如说你的ip是 10.1.4.166 主机名是centos1

    那么配置: 10.1.4.166 centos1

    展开全文
  • 首先我们看一下websocket的出现背景,我们知道http系列协议是建立在tcp上的,理论上,他是可以可以双向通信的。...每次都是客户端请求,服务器...但是我们知道tcp协议的缺点就是,三次握手需要时间,再加上开始等特...

    首先我们看一下websocket的出现背景,我们知道http系列协议是建立在tcp上的,理论上,他是可以可以双向通信的。但是http1.1之前,服务器没有实现推送的功能。每次都是客户端请求,服务器响应。下面看一下http协议关于请求处理的发展。

    1. http1.0的时候,一个http请求的生命周期是客户端发起请求,服务器响应,断开连接。但是我们知道tcp协议的缺点就是,三次握手需要时间,再加上慢开始等特性,每一个http请求都这样的话,效率就很低。
    2. http1.1的时候,默认开启了长连接(客户端请求中设置了keep-alive头),服务器处理一个请求后,不会立刻关闭连接,而是会等待一定的时间。如果没有请求才关闭连接。这样浏览器不仅可以在一个tcp连接中,不断地发送请求(服务器也会限制一个连接上可以处理的请求阈值),甚至可以一次发很多个请求。这就是http1.1的管道化(pipeline)技术。但是他也有个问题,因为对于基于http协议的客户端来说,虽然他可以发很多请求出去,但是当一个请求对于的回包回来时,他却无法分辨是属于哪个请求的。所以回包只能按请求顺序返回,这就引来了另一个问题-线头阻塞(Head-of-Link Blocking)。并且http1.1虽然支持长连接,但是他不支持服务端推送(push)的能力。如果服务器有数据要给客户端,也只能等着客户端来取(pull)。
    3. 来到了http2.0,不仅实现了服务器推送,还使用了帧(iframe),流(stream)等技术解决了线头阻塞的问题,http2.0在一个tcp连接中,可以同时发送多个http请求,每个请求是一个流,一个流可以分成很多帧,有了标记号,服务器可以随便发送回包,客户端收到后,根据标记,重新组装就可以。
      以上是http协议的关于请求的一些发展,而websocket就服务端推送提供了另外一种解决方案。他本质上是在tcp协议上封装的另一种应用层协议(websocket协议)。因为他是基于tcp的,所以服务端推送自然不是什么难题。但是在实现上,他并不是直接连接一个tcp连接,然后在上面传输基于websocket协议的数据包。他涉及到一个协议升级(交换)的过程。我们看看这个过程。

    1 客户端发送协议升级的请求。在http请求加上下面的http头

    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
    Sec-WebSocket-Key: k1kbxGRqGIBD5Y/LdIFwGQ==
    Sec-WebSocket-Version: 13
    Upgrade: websocket
    

    2 服务器如果支持websocket协议的话,会返回101状态码表示同意协议升级,并且支持各种配置(如果服务器不支持某些功能或版本,或告诉客户端,客户端可以再次发送协议升级的请求)。服务会返回形如下面的http头(可以参考websocket协议)。

    Connection: Upgrade
    Sec-WebSocket-Accept: y73KZR4t+hqD6KKYbkx2tULfBsQ=
    Upgrade: websocket
    

    3 这样就完成了协议的升级,后续的数据通信,就是基于tcp连接之上,使用websocket协议封装的数据包。

    下面我们通过wireshark来了解这个过程。首先我们启动一个服务器(ip:192.168.8.226)。

    var http = require('http');
    var fs = require('fs');
    const WebSocket = require('ws');
    // 如果在浏览器控制台进行测试,可以不起http服务器
    const server = http.createServer(options,function(req,res){
        res.end(fs.readFileSync(`${__dirname}/websocket.html`));
    }).listen(11111);
    
    const wss = new WebSocket.Server({ server }); 
    wss.on('connection', function connection(ws) {
      ws.on('message', function(message) {
        ws.send(message);
      });
    
      ws.send('get it');
    });
    

    我们可以直接在浏览器控制台进行测试

    var ws = new WebSocket("ws://192.168.8.226:11111");
    // 连接上后执行
    ws.send(11)
    

    这时候,我们看看wireshark的包。

    2f742adc93ebb4a7194d276cf3a685d1.png

    首先看前面三条记录,这是tcp三次握手的数据包。这个我们都了解了,就不展示。接着看第四条记录。展开后如下。

    699a3dac61c7ef373e1b55735ef9429b.png

    我们看到建立tcp连接后,浏览器发了一个http请求,并带上了几个websocket的数据包。接着看下面的一条。

    a01873d6b0458203183863a22cbb9163.png

    服务返回了同意升级协议或者说交换协议。从服务器代码中我们看到,在建立连接的时候我们给浏览器推送了一个get it的字符串。继续看上面的记录。

    6ec06fe1d7a1e57c18f5343c5bea20b2.png

    这就是服务器给浏览器推送的基于websocket协议的数据包。具体每个字段什么意思,参考websocket协议就可以。继续往下看一条记录是针对服务器推送的数据包的一个tcp的ack。最后我们可以顺便看看最后三条写着keep-alive的记录。这就是之前文章里讲到的tcp层的keep-alive。因为我们一直没有数据传输,所以tcp层会间歇性地发送探测包。我们可以看看探测包的结构。

    de03cffc924689462ec071a704f66480.png

    有一个字节的探测数据。如果这时候我们发送一个数据包给服务器,又是怎样的呢。

    3e45031e0d5007a6b8f9ca4098464a53.png

    白色背景的三条数据,分别是浏览器发送给服务器的数据,服务器推送回来的数据。tcp的ack。我们发现,服务器给浏览器推送的时候,浏览器会发送ack,但是浏览器给服务器发送的时候,服务器貌似没有返回ack。下面我们看看为什么。首先我们看浏览器发出的包。

    3f1ee0b8fdfc9d69874e591dfcb53fcf.png

    再看看服务器给浏览器推送的数据包。

    455c691d9a0e508291de703a1400cfb9.png

    我们发现服务器(tcp)推送消息的时候把ack也带上了。而不是发送两个tcp包。这就是tcp的机制。tcp不会对每个包都发ack,他会累积确认(发ack),以减少网络的包,但是他也需要保证尽快地回复ack,否则就会导致客户端触发超时重传。tcp什么时候发送确认呢?比如需要发送数据的时候,或者超过一定时间没有收到数据包,或者累积的确认数量达到阈值等。既然研究了tcp,我们不妨多研究点,我们看一下,如果这时候关闭服务器会怎样。

    86598b1a8ebe3a382e468d2779b5adbe.png

    服务器会发送一个重置包给浏览器,告诉他需要断开连接。继续,如果是浏览器自己调用close去关闭连接会怎样。

    7d9f365121cc1b97ef81074b55f9af51.png

    我们看到websocket首先会发送一个FIN包给服务器,然后服务器也会返回一个FIN包,然后才开始真正的四次挥手过程。并且四次挥手的第一个fin包是服务器发的。

    我们再来看看安全版本的websocket。我们启动一个https服务器。

    var https = require('https');
    var fs = require('fs');
    const WebSocket = require('ws');
    
    var options = {
        key: fs.readFileSync('./server-key.pem'),
        ca: [fs.readFileSync('./ca-cert.pem')],
        cert: fs.readFileSync('./server-cert.pem')
    };
    
    const server = https.createServer(options,function(req,res){
        res.end(fs.readFileSync(`${__dirname}/websocket.html`));
    }).listen(11111);
    
    const wss = new WebSocket.Server({ server });
    
    wss.on('connection', function connection(ws) {
      ws.on('message', function(message) {
        ws.send(message);
      });
    });
    

    然后在浏览器控制台执行。

    var ws = new WebSocket("wss://192.168.8.226:11111");
    ws.sned(11);
    

    然后来看看wireshark。

    40125b34d17851cab0c1ce345654d9ea.png

    首先建立tcp连接,然后建立tls连接。后续的数据通信就可以基于加密来进行了。不再重复。后续分析tls协议的时候再分析。

    经过一系列的分析,我们对websocket协议应该有了更多的了解,最后再说一个关于websocket的点。我们发现如果在websocket连接上,一直不通信的话,websocket连接所维持的时间是依赖tcp实现的。因为我们发现tcp层会一直发送探测包。达到阈值之后,连接就会被断开。所以我们想维持websocket连接的话,需要自己去发送心跳包,比如ping,pong。

    总结:本文分析了websocket的基本原理,但不涉及协议的内容,如需了解协议的内容,可以参考rfc文档。

    展开全文
  • 公司项目有个需求,将发生的事件使用webSocket推送到前端(包括一张高清图),要求1秒之内在web上显示,且不能失真。 方案1:首先是将图片转换成base64,作为字符串推送给前端,但是推送过来的信息量太大,导致接收...

    1、背景

    公司项目有个需求,将发生的事件使用webSocket推送到前端(包括一张高清图),要求1秒之内在web上显示,且不能失真。

    方案1:首先是将图片转换成base64,作为字符串推送给前端,但是推送过来的信息量太大,导致接收信息延时。

    方案2:改为推送文件路径,但是web请求图片会有0.6-0.7毫秒的时间,一旦推送过多,会更慢,且web加载图片时会有短暂的闪烁。

    2、解决方案

    将字符串信息压缩后传给web,但是java对于字符串压缩量不大,因此通过node来进行处理。使用开源插件pako。

    将node作为服务端,java后台(客户端)通过socket将字符串发给node,node将压缩后的图片发送给java后台(也可以直接通过node服务器发给web,当前项目重构量比较大,未使用)。再发给web去解压。

    3、代码

    node服务端代码

    /**
     * js压缩函数
     * @type {{}}
     */
    const pako = require('pako');
    /**
     * 导入websocket
     */
    const websocket = require('./websocket.js');
    
    var net = require('net');
    var HOST = '127.0.0.1';
    var PORT = 11111;
    
    /**
     * 压缩函数
     * @param str
     * @returns {void | number | * | Deflate.result}
     */
    const gzip = function (str){
        const _str = str || args[0] || '';
        return pako.deflate(_str, { to: 'string' });
    };
    
    
    net.createServer(function(socket) {
        console.log('connection: ' + socket.remoteAddress + ':' + socket.remotePort);
        /**
         * 连接后 接收消息
         */
        let __data = '';
        const BEGIN = '0x420x450x470x490x4E';
        const END = '0x450x4E0x44';
    
        const setData = function(data) {
            // endsWidth 无用
            if (data.includes(END)) {
                const _data = gzip(__data.replace(BEGIN, '').replace(END, ''));
                // 测试代码
                // websocket.connections.forEach(function(conn) {
                //     conn.sendText(_data);
                // });
                socket.write(_data + '\n');
                __data = '';
            }
        };
    
        socket.on('data', function(data) {
            data = data.toString();
            const len = data.length;
            if (data.startsWith(BEGIN)) {
                __data = data;
            } else {
                __data += data;
            }
            setData(data);
        });
    
        /**
         * 监听关闭状态
         */
        socket.on('close', function(data) {
            console.log('close: ' + socket.remoteAddress + ' ' + socket.remotePort);
        });
    }).listen(PORT, HOST);
    
    console.log('Server listening on ' + HOST +':'+ PORT);
    
    

    node websocket测试代码

    const ws = require('nodejs-websocket')
    
    const AllUserData = [];
    
    // Scream server example: 'hi' -> 'HI!!!'
    const connection = function (conn) {
        conn.on('text', function (str) {
            AllUserData.push({
                'id':str,
                'ws':conn
            });
            conn.sendText(str.toUpperCase()+'!!!')
        });
        conn.on('close', function (code, reason) {
            console.log('Connection closed')
            // 当用户退出的时候捕捉到退出的用户
            for (let i in AllUserData) {
                if (AllUserData[i].ws == conn) {
                    console.log(AllUserData[i])
                }
            }
        });
        conn.on('error', function(code) {
            // 某些情况如果客户端多次触发连接关闭,会导致connection.close()出现异常,这里try/catch一下
            try {
                conn.close()
            } catch (error) {
                console.log('close异常', error)
            }
            console.log('异常关闭', code)
        });
    }
    const server = ws.createServer(connection).listen(8001);
    
    module.exports = server;
    
    // console.log(server.connections);

    java客户端代码

    import java.io.*;
    import java.net.Socket;
    
    public class Pako {
        private Socket socket = null; // Socket 对象
        private PrintWriter printWriter = null; // 发送事件对象
        private BufferedReader bufferedReader = null; // 接收事件对象
        public Pako() throws IOException {
            socket = new Socket("127.0.0.1", 11111);
            printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        }
    
        /**
         * @param str
         * @return
         * @throws IOException
         */
        public String getPakoDataBySocket(String str) throws IOException {
            // 事件发送
            this.sendMsg(str);
            // 事件接收
            return this.getMsg();
        }
    
        /**
         * 关闭连接
         * @throws IOException
         */
        public void closeSocket() throws IOException {
            socket.close();
        }
    
        /**
         * 发送事件
         * @param str
         * @throws IOException
         */
        public void sendMsg(String str) throws IOException {
            printWriter.println(str);
            printWriter.flush();
        }
    
        /**
         * 接收事件
         * @throws IOException
         * @return
         */
        private String getMsg() throws IOException {
            return bufferedReader.readLine();
        }
    }

    java客户端测试代码

    import java.io.IOException;
    import java.util.Date;
    
    public class Test {
    
        public static Pako pako;
        static {
            try {
                pako = new Pako();
            } catch (IOException e) {
            }
        }
    
        public Test() throws IOException {
        }
    
        public static void main(String[] args) throws IOException {
            Test _test = new Test();
            _test.test();
        }
    
        public void test() throws IOException {
            String b64Data = "H4sIAAAAAAAAAJ3UMQ7CMAwF0KugP2ewEzdpcxXUAbWAOiHUMqCqdyeVQAobfGXIYL8hP5ZXnEdkeNEk6vUgXTbLonC4zMjHFY/5Wm511ekdTsOCLKVp2rlIKOA2jTuBot//cr7BhobEwsbAloY8kDGyqoQ5H/oHsdwQ21cCmaspCz0L2jcYOgLHhNGw4TT1yVmBpuS9PZHWY35siqnxvimEvpE9FY4peQhfbhO0FDnuFqWAEAAA=end";
            for (int j = 0; j < 5; j++) {
                try{
                    String _str = "";
                    for (int i = 0; i < 1000; i++) {
                        _str += b64Data;
                    }
                    _str = "0x420x450x470x490x4E"  + _str + "0x450x4E0x44";
                    System.out.println(new Date().getTime());
                    String str = pako.getPakoDataBySocket(_str);
                    Thread thread = Thread.currentThread();
                    thread.sleep(1);//暂停1毫秒后程序继续执行1
                }catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
            }
            System.out.println(new Date().getTime());
        }
    
    }
    

    web客户端测试代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>django-websocket</title>
        <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
        <script src="./node_modules/pako/dist/pako.min.js"></script>
        <script type="text/javascript">//<![CDATA[
        $(function () {
            function cnn() {
                if (window.s) {
                    window.s.close()
                }
                /*创建socket连接*/
                var socket = new WebSocket("ws://127.0.0.1:8001");
                socket.onopen = function () {
                    console.log('WebSocket open');//成功连接上Websocket
                };
                socket.onmessage = function (e) {
    
                    const str =  pako.inflate(e.data, { to: 'string' });
                    console.log(new Date().getTime())
                    console.log(str.length);//打印出服务端返回过来的数据
                    $('#messagecontainer').prepend('<p>' + str + '</p>');
                };
                // Call onopen directly if socket is already open
                if (socket.readyState == WebSocket.OPEN) socket.onopen();
                window.s = socket;
            }
            cnn();
            $('#connect_websocket').click(function () {
                cnn();
            });
            $('#send_message').click(function () {
                //如果未连接到websocket
                if (!window.s) {
                    alert("websocket未连接.");
                } else {
                    window.s.send($('#message').val());//通过websocket发送数据
                }
            });
            $('#close_websocket').click(function () {
                if (window.s) {
                    window.s.close();//关闭websocket
                    console.log('websocket已关闭');
                }
            });
        });
        //]]></script>
    </head>
    <body>
    <br>
    <input type="text" id="message" value="user1"/>
    <button type="button" id="connect_websocket">连接 websocket</button>
    <button type="button" id="send_message">发送 message</button>
    <button type="button" id="close_websocket">关闭 websocket</button>
    <h1>Received Messages</h1>
    <div id="messagecontainer">
    </div>
    </body>
    </html>
    

    4、耗时(24万字符长度,包含解压缩大概100毫秒)目前未找到socket一次传输大批量数据的方法

    发送事件:0  发送时间:1571033967852
    发送事件:1  发送时间:1571033967939
    发送事件:2  发送时间:1571033967989
    发送事件:3  发送时间:1571033968013
    发送事件:4  发送时间:1571033968053

     

    展开全文
  • 前端使用sockjs,后台使用spring的websocket框架结果在一个网络较的地方,发现tomcat报错信息:Oct 28, 2015 10:10:43AM org.apache.catalina.core.StandardWrapperValve invokeSEVERE: Servlet.service()for ...
  • 首先我们看一下websocket的出现背景,我们知道http系列协议是建立在tcp上的,理论上,他是可以可以双向通信的。...每次都是客户端请求,服务器...但是我们知道tcp协议的缺点就是,三次握手需要时间,再加上开始等特...
  • WebSocket学习

    2015-08-28 15:21:00
    其实我们所用的程序是要经过两层代理的,即HTTP协议在Nginx等服务器的解析下,然后再传送给相应的... 本身接线员基本上速度是足够的,但是每次都卡在客服(Handler)了,老有客服处理速度太。,导致客服不够。 W...
  • websocket mvc集成

    2018-09-28 17:12:32
    网页版的即时聊天如果用ajax轮询,在线人数少无所谓,一旦在线人数特别多,服务器压力就很大,速度会特别,而且ajax的定时刷新也不是真正意义上的即时聊天,是由网页刷新时间决定的 那么,websocket就是一个特别...
  • webSocket的理解

    2020-12-11 11:09:24
    轮询实现简单,但在高并发场景中会严重拖服务端的运行效率。这种方式并不可取。传统的解决方案还有很多,但无论哪种解决方案都有自身的缺陷。于是有了WebSocketWebSocket是一种在单个TCP连接上进行全双工通信...
  • Websocket出现的错误

    2019-10-02 15:51:18
    前端使用sockjs,后台使用spring的websocket框架 结果在一个网络较的地方,发现tomcat报错信息: Oct 28, 2015 10:10:43 AM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service...
  • 0.推荐阅读由于国庆前后实在是太多事了,导致这篇文章更新的比较,忘记了的同学可以先阅读下上篇文章,本篇文章将在上篇的基础上进行。spring boot+ websocket 推送1.配置类上篇文章我们提到过stomp.js 和 sockjs...
  • WebSocket API

    2017-10-13 16:38:14
    当前的 HTTP 标准协议很,因为它必须从服务器请求文档而且必须等待该文档发送,才能显示网页。使用 WebSocket,你可以使用文本、二进制数组或 BLOB 立即发送和接收你的数据。Internet Explorer 10 和使用 ...
  • 理解websocket的原理

    2020-06-20 17:21:36
    首先我们看一下websocket的出现背景,我们知道http系列协议是建立在tcp上的,理论上,他是可以可以双向通信的。但是http1.1之前,服务器没有实现推送的功能。每次都是客户端请求,服务器响应。下面看一下http协议...
  • websocket 用IP访问OutputStream.write就很快 配域名访问就很 server往浏览器写流的时候,IP本地和测试环境就很快就能写完,但是正式环境域名就会有500ms左右卡顿。 主要代码 public void onReadText(final...
  • 目前在开发一个系统,系统提供一些计算服务,但是这些计算服务比较耗时,快的很快,的可能要几十秒或者几分钟才能出结果,计算结果出来后需要返回给前端,是采用轮询还是websocket比较好? websocket的实时性...
  • HTTP/2 和 Websocket

    2019-01-19 10:14:00
    本文转自我的博文HTTP/2 和 Websocket HTTP/2 是什么 这篇文章讲的比较详细: 它是 google 提出的开源协议,旨在提高网络传输效率 它是二进制协议 它采用多路复用解决 HTTP 1.1 的 head-of-line ...
  • <p>My <a href="https://github.com/gorilla/websocket" rel="nofollow noreferrer">Gorilla WebSocket</a> and <a href="https://github.com/websockets/ws" rel="nofollow noreferrer">node-ws</a> servers below:...
  • vue中使用websocket通信接收后台数据

    千次阅读 热门讨论 2019-08-20 16:52:45
    项目中因为有的数据使用分页后数据加载还是很,所以考虑使用websocket来解决。后端获取到数据库数据后就依次返回给前端,这样就不需要等分页数据全部获取后才返回。 1、需求概述 点击按钮后才开启websocket连接...
  • websocket实现类似于QQ的聊天功能

    千次阅读 2018-07-27 17:37:48
    http单向通讯协议,请求只能是客户端发起,且是无状态的,而websocket是双向通讯协议,可以有服务器发起也可以是客户端发起,用http实现聊天功能一般是通过轮询,但是轮询非常浪费服务器资源,而且,亲测过 ...
  • HTTP协议的特性:属于“请求-响应”模型,只有客户端发起了请求消息,服务器才能给出响应消息,没有请求,就没有...WebSocket协议的特性:属于“广播-收听”模型,只要客户端连接到服务器上,就不再断开(永久连接),

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 148
精华内容 59
关键字:

websocket慢