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 blocke.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 openif (socket.readyState == WebSocket.OPEN) socket.onopen();window.s = socket;}cnn();$('#connect_websocket').click(function () {cnn();});$('#send_message').click(function () {//如果未连接到websocketif (!window.s) {alert("websocket未连接.");} else {window.s.send($('#message').val());//通过websocket发送数据}});$('#close_websocket').click(function () {if (window.s) {window.s.close();//关闭websocketconsole.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

解决webSocket中传输base64图片过大时的过慢问题相关推荐

  1. 解决Chrome中UEditor插入图片的选择框加载过慢问题

    解决Chrome中UEditor插入图片的选择框加载过慢问题 ../resources/plugins/ueditor/ueditor.all.js 中line24489/24498中的 accept ...

  2. vue实战(1)——解决element-ui中upload组件使用多个时无法绑定对应的元素

    解决element-ui中upload组件使用多个时无法绑定对应的元素 以前写的项目关于图片上传的都是单张或几张图片上传(主要是基于vue的element),图片路径都是固定写的,所以遇见过列表中多个 ...

  3. Vue中插入base64图片

    1.template模板中写入img标签 <!-- base64图片 --><img :src="formLabelAlign.deptPic" /> 2. ...

  4. html中鼠标悬停图片变大,JavaScript通过mouseover()实现图片变大效果的示例

    图片提示 body{ margin:0; padding:40px; background:#fff; font:80% Arial, Helvetica, sans-serif; color:#55 ...

  5. php中怎样把图片改大,PHP怎么批量修改图片大小?

    相信大家和我一样,网站的图片大小不一,有的错略图小的才几KB,大的可能有几MB,为了提高用户体验,我们需要将图片的缩略图统一大小,也就是宽高,我的网站8000多条张图片之前没有很好的方法去处理,有想过 ...

  6. word文档中插入的图片太大如何压缩变小的问题

    如果对word文档中图片的分辨率有特别的要求的话,直接点击图片,在出现的编辑菜单中用"压缩"命令就可以了,见下图. 转载于:https://www.cnblogs.com/ljy3 ...

  7. CSS | 解决html中img标签图片底部存在空白缝隙的问题

    目录 问题描述 原因分析 解决方案 写在最后 问题描述 在学习CSS的过程中,我们经常会遇到图片底侧存在空白缝隙的问题. 代码示例: <!DOCTYPE html> <html la ...

  8. 解决webSocket中使用@Autowired注入为空的办法

    思路: 1.在启动类向webSocketServer中注入ApplicationContext 2.在你的webSocketServer类中通过ApplicationContext.getBean() ...

  9. 解决Vue中动态src图片不显示

    图片的本地相对路径需要使用require包裹 <template><div><div v-for="item in imgList" :key=&qu ...

最新文章

  1. 微软宣布Azure Functions正式支持Java
  2. stackexchange.mysql_.net core使用redis基于StackExchange.Redis
  3. 拿起电话就开始给(飞鸽传书3.0)
  4. php转移单引号,php如何转义单引号
  5. QNX多线程同步之Barrier(屏障)
  6. sql程序实现事物锁表和解锁_怎样用SQL给SQL2880特定表加锁解锁
  7. 使用sqoop导出mysql数据时错误处理【com.mysql.jdbc.RowDataDynami】
  8. 第 3 章 MybatisPlus 注入 SQL 原理分析
  9. Lotus Sametime Server R8.x 标准版部署排错
  10. 我们一起踩过的坑----react(antd)(二)
  11. 力软快速开发平台源码7.0.6
  12. eaxyexcel获取指定行,获取总行数
  13. 淘金网UCskype即时通讯软件定制
  14. Android11(R)新特性梳理
  15. 形容计算机专业好句子,形容专业水平高的词句
  16. 推荐:大文件查找,快速扫描,图像分析并清理硬盘垃圾文件的绝佳好工具!
  17. MaxCompute UDF系列之拼音转换
  18. 微信公众号客服功能如何开通?
  19. fdisk 命令实现磁盘分区详细教程
  20. “我想学习人工智能与机器学习,该从何做起?”

热门文章

  1. vtk教程第八章 高级数据表示
  2. 电脑系统重装要多久?
  3. 捷配精密金属,感受钢铁直男的力量
  4. 【读书笔记】《CSS3艺术:网页设计案例实战》——【一】伪元素、边框、背景属性
  5. 第四课:vi编辑器和c语言
  6. 大数据框架 Flink、Blink、Spark Streaming、Structured Streaming 和 Storm 之间的区别
  7. 初识Python必看基础知识~ 续(5)进阶之路~再接再厉~
  8. 不容错过 名片卡证模板素材网站
  9. 深圳住房公积金提取攻略
  10. 含泪控诉人类科技史上的三个顶级“渣男”!