精华内容
下载资源
问答
  • web 实时刷新 websocket 大数据

    千次阅读 2018-04-03 17:16:36
    有如下需求:有如果个实验设备运行并且将运行数据通过socket发送到分析平台,分析平台通过运行socket作业来完成对socket数据的接收,同时还需要对接收到的socket数据进行解析并且可以通过一个数据看板对数据实时监控...

     最近在做的一个项目,是一个大数据分析平台,有如下需求:有如果个实验设备运行并且将运行数据通过socket发送到分析平台,分析平台通过运行socket作业来完成对socket数据的接收,同时还需要对接收到的socket数据进行解析并且可以通过一个数据看板对数据实时监控。如下图所示:

           

           

    选择websocket的原因,就是看板页面不必每次都去定时的请求数据,而是一旦websocket服务器发现有新数据则直接推送给客户端进行渲染,减少了占用的宽带和服务器资源。由于socket数据量多且快,所以如果将数据直接存入到传统的关系型数据库则会遇到效率瓶颈,这时候就必须要有一个缓存,redis基于内存且最大的特点就是快,用作缓存再合适不过,待作业结束后再将数据保存进hbase中即可。看板用到了baidu的echarts3折线图。


    接收到的socket数据源源不断的被写入到redis中,接收到的数据格式类似于:数据量1|数据量2|数据量3|日期1|日期2...websocket的任务就是将这些数据交给看板进行渲染,那么怎么去拿到数据呢?就是websocket服务端定时的去redis拿,一旦有新数据则推送给看板。


     首先开发websocket服务端,ServerSocket采用单例模式,因为是集成服务,所以如果需要关闭服务的话可以直接将ServerSocket关闭即可,服务器端代码如下:

    [java] view plain copy

    1.     PrintWriter pw = getWriter(socket);    

    2.                 byte[] buf = new byte[1024];    

    3.                 int len = in.read(buf, 01024);    

    4.                 byte[] res = new byte[len];    

    5.                 System.arraycopy(buf, 0, res, 0, len);    

    6.                 String key = new String(res);    

    7.                 if (!hasHandshake && key.indexOf("Key") > 0) {    

    8.                     key = key.substring(0, key.indexOf("==") + 2);    

    9.                     key = key.substring(key.indexOf("Key") + 4, key.length())    

    10.                         .trim();    

    11.                  key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";    

    12.                 MessageDigest md = MessageDigest.getInstance("SHA-1");    

    13.                  md.update(key.getBytes("utf-8"), 0, key.length());    

    14.                 byte[] sha1Hash = md.digest();    

    15.                  sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();    

    16.                 key = encoder.encode(sha1Hash);    

    17.                  pw.println("HTTP/1.1 101 Switching Protocols");    

    18.                 pw.println("Upgrade: websocket");    

    19.                  pw.println("Connection: Upgrade");    

    20.                 pw.println("Sec-WebSocket-Accept: " + key);    

    21.                  pw.println();    

    22.                 pw.flush();    

    23.                  hasHandshake = true;    

    24. }  

     

          上面这段代码是websocket握手的代码,握手之后获取看板传来的id,然后再去redis请求数据,发现新数据则推送给看板,推送的代码:

    [java] view plain copy

    1.     /** 

    2.          * 推送数据到客户端 

    3.          *  

    4.          * @param byteBuf 

    5.          * @param finalFragment 

    6.          * @throws IOException 

    7.          */  

    8.         private void responseClient(ByteBuffer byteBuf, boolean finalFragment)  

    9.                 throws IOException {  

    10.         OutputStream out = socket.getOutputStream();  

    11.          int first = 0x00;  

    12.         // 是否是输出最后的WebSocket响应片段  

    13.          if (finalFragment) {  

    14.             first = first + 0x80;  

    15.              first = first + 0x1;  

    16.         }  

    17.          out.write(first);  

    18.   

    19.          if (byteBuf.limit() < 126) {  

    20.             out.write(byteBuf.limit());  

    21.          } else if (byteBuf.limit() < 65536) {  

    22.             out.write(126);  

    23.              out.write(byteBuf.limit() >>> 8);  

    24.             out.write(byteBuf.limit() & 0xFF);  

    25.          } else {  

    26.             out.write(127);  

    27.              out.write(0);  

    28.             out.write(0);  

    29.              out.write(0);  

    30.             out.write(0);  

    31.              out.write(byteBuf.limit() >>> 24);  

    32.             out.write(byteBuf.limit() >>> 16);  

    33.              out.write(byteBuf.limit() >>> 8);  

    34.             out.write(byteBuf.limit() & 0xFF);  

    35.    

    36.         }  

    37.    

    38.         // Write the content  

    39.          out.write(byteBuf.array(), 0, byteBuf.limit());  

    40.         out.flush();  

    41.      }  


         
    服务器端代码的核心基本上是这些,那么现在是前段的代码了,因为是使用了echarts的折线图,所以至于echarts的使用这里不赘述,在页面加载完毕后连接websocket服务端并且发送id以及其他的一些参数,连接的代码如下所示:

    [javascript] view plain copy

    1.     function connect(form_data) {  

    2.         try {  

    3.             var host = "ws://localhost:8000";  

    4.             websocket = new WebSocket(host);  

    5.       

    6.             websocket.onopen = function() {  

    7.                 if (form_data != null)  

    8.                     sendToServer(form_data);// 与服务器端连接成功后需要将作业实例ID发送给服务器端  

    9.             };  

    10.         websocket.onmessage = function(event) {// 服务器端推送过来的数据格式必须是:数据量|日期  

    11.              // ,其中日期格式为:yyyy-MM-dd HH:mm:ss:SS  

    12.             processMultiData(event.data);// 处理多行数据  

    13.              if (option2.series.length == 0)  

    14.                 genLegend();  

    15.              genSeries();  

    16.             myChart.setOption(option2);  

    17.          };  

    18.         websocket.onclose = function() {  

    19.              // alert('连接关闭');  

    20.         };  

    21.      } catch (exception) {  

    22.         alert("error");  

    23.      }  

    24. }  


           
    发送数据给服务器端的代码:

    [javascript] view plain copy

    1.     function sendToServer(option_data) {// 发送实例ID往ws服务器端  

    2.         try {  

    3.             websocket.send(option_data);  

    4.         } catch (exception) {  

    5.             alert("发送实例ID出错!" + exception);  

    6.         }  

    7.     }  


         
      websocket的几个方法分别是onopen:连接上后执行;onmessage:接收到数据后执行的逻辑,还有onclose以及onerror都很好理解啦。

    ==

    用 SqlDependency 
    自动通知,
    只有数据表有变化,就自动反映出来了,

     

    项目是一个实时监控系统,有一个告警数据需要4秒内响应,可是告警数据的入库不是在web平台进行无法跟踪,是其他系统入库。领导希望web告警的信息展示能马上响应,原先做法是页面每30刷新一次,如果要在4秒内做响应就要改成4秒刷新这样对数据访问太过频繁,小弟不知如何解决希望各位帮助一下

     

    实时的开启 和 关闭。暂停播放。

     

    有三种方式:
    1,ajax短连接:客户端每隔一秒钟发一次请求,服务器收到请求后会立刻返回结果,不管有没有新数据。
    2,ajax长连接:客户端发送一次请求,服务器端收到请求后查询有没有新数据,如果没有新数据就阻塞这个请求,直到有新数据或者超时为止。客户端每次收到请求返回结果后立刻再发一次请求。comet貌似就是这个原理。
    3,WebSocket:这就不是一个HTTP协议了,而是一个tcp协议,而且Socket这个玩意顾名思义就是一个流了,可以双向操作。缺点是有些浏览器不支持。

    对比延迟:
    假设网络延迟是m毫秒,那么ajax短连接的延迟在m到1000毫秒之间,另外两种基本只有m毫秒的延迟。
    对比资源占用:
    应该是1>2>3。但是1和2的比较要看情况,如果两次请求间隔时间很长的话应该是2>1>3。

     

    实时通信技术在股票价格、新闻报道、余票查询、交通情况等领域中有着广泛的应用,

    但是目前的实时Web应用的实现方式,都是基于HTTP协议,围绕着轮询和其他服务器推送技术展开的,所以不可避免的产生大量的额外的报头数据,造成传输时延。HTML5中的WebSocket协议是基于浏览器与服务器全双工通信的新理论。客户端通过WebSocket与服务器进行通信时,只有第一次握手交互信息比较复杂,在握手成功后便进入全双工的数据传输阶段,降低了数据流量与传输时延。

    setInterval用这个方法,页面自动刷新,N秒钟执行一次。

    股市看盘,2秒获取一次http。

     

    Web页面实时刷新技术探讨

    一、总述

    随着网络技术的飞速发展,使用B/S结构来实现项目应用已经越来越多,而实时监控一直都是多数行业软件所必备的功能,由此使用Web页面来实现实时监控成了一种必然的需求。

    二、实时刷新技术

    1、传统的页面刷新方式

    传统的页面刷新方式很多,常见的有页面间隔一定的时间自动刷新、ActiveX控件、Applet等。

    采用页面间隔一定的时间自动刷新的方式,是在网页的头部加入一下代码:

    <metahttp-equiv="refresh" content="20;url=newPage">

    这里是经过20秒跳转到一个新页面,可以将“newPage”设置为本页面即为刷新本页面,刷新间隔时间可以修改“20”为任意时间。通过这种方式如果并发和访问量较大,服务器就有可能承受不了这种压力,从而造成服务器死机。

    使用ActiveX控件的方式需要每个客户端下载安装ActiveX控件,并且客户端浏览器只能使用Windows的IE浏览器。

    同样使用Applet需要客户端安装Java运行时。

    这些传统的页面刷新方式都或多或少的存在着一些确定,在Web项目应用中的使用也越来越少。

    2、Ajax轮询

    Ajax轮询方式是使用客户端脚本,通过XMLHttpRequest来定时发送请求,从而查询页面数据的更新情况。通过这种方式,程序实现方便简捷,但客户端频繁的发送请求会给服务器带来很大的压力和客户端处理器负载,如果服务器端没有更新时,这种轮询访问服务器便是无意义的,并且耗费了网络资源与CPU处理资源。

    3、DWR服务器Push

    DWR的反转AJAX功能允许我们从服务器端来控制客服端,而不需要客户端的请求,服务器可以自动把消息发给指定的客户端。DWR的Push技术是让服务器每次发送广播时,把这个广播推送给客户端,而不用客户端去刷新,DWR的推送是基于长连接的,性能优越。

    4、与服务端建立长连接

    与服务器建立长连接,也就是在显示数据页面中嵌入一个隐藏页面,该隐藏页面主要完成取服务器端所要显示的数据,并且将该页面显示数据的方法写成一个死循环,以此来保持与服务器端的长连接。

    同样以服务器端通过手动控制按钮产生一张图片,客户端显示最新图片及图片的信息内容作为实例加以说明。

    5、RTMP协议传输

    随着网络技术的迅猛发展,视频、音频等多媒体通信需求越来越多,Adobe公司开放了RTMP(theReal-time Messaging Protocol)协议规范,RTMP协议作为客户端和服务器端的传输协议,这是一个专门为高效传输视频、音频和数据而设计的 TCP/IP 协议。其优秀产品Flex是用于构建和维护在所有主要浏览器、桌面和操作系统一致地部署的极具表现力的 Web 应用程序的高效率的开放源码框架。

    从目前的应用来说,RTMP主要用于音、视频的传输,流视频服务器就是FMS(Flash Media Server),其原称为FCS(Flash Communication Server),技术范畴能应用到诸如Flash聊天室、视频会议等领域。

    以一个实现聊天功能的Flex程序为例,

     

    从目前实际应用来说,以上四种实现Web页面实时刷新都是可行方案,各有优缺点与适用的具体环境。

    Ajax轮询方式比较适用于需要传输的数据量较小的情况,可通过客户端首先轮询服务器端的更新标识,若有更新再下载更新数据,这样能减小一部分服务器的压力。

    DWR反转AJAX功能,真正实现了从服务器端将更新“推”到客户端。

    与服务器端建立长连接的方式,也是通过客户端的请求获取更新数据的。

    通过RTMP协议传输,主要适用于音、视频的数据传输,比较适用于视频聊天室,目前视频服务器FMS的费用较高(4500元100个客户端),与服务器的连接数受到限制。

    总体来看,要实现Web页面的实时刷新,肯定是会给服务器带来一定的压力的,对于具体项目的不同需求,可选择合适的方式来实现Web页面的实时刷新。

           Web页面实时刷新技术探讨 - CSDN博客

    展开全文
  • Web页面实时刷新技术探讨

    万次阅读 2017-09-05 11:01:49
    ...随着网络技术的飞速发展,使用B/S结构来实现项目应用已经越来越多,而实时监控一直都是多数行业软件所必备的功能,由此使用Web页面来实现实时监控...二、实时刷新技术 1、传统的页面刷新方式 传统的页面

    原文地址:http://blog.csdn.net/anluo_sun/article/details/48652215


    一、总述

    随着网络技术的飞速发展,使用B/S结构来实现项目应用已经越来越多,而实时监控一直都是多数行业软件所必备的功能,由此使用Web页面来实现实时监控成了一种必然的需求。

     

    二、实时刷新技术

    1、传统的页面刷新方式

    传统的页面刷新方式很多,常见的有页面间隔一定的时间自动刷新、ActiveX控件、Applet等。

    采用页面间隔一定的时间自动刷新的方式,是在网页的头部加入一下代码:

    <meta http-equiv="refresh" content="20;url=newPage">

    这里是经过20秒跳转到一个新页面,可以将“newPage”设置为本页面即为刷新本页面,刷新间隔时间可以修改“20”为任意时间。通过这种方式如果并发和访问量较大,服务器就有可能承受不了这种压力,从而造成服务器死机。

    使用ActiveX控件的方式需要每个客户端下载安装ActiveX控件,并且客户端浏览器只能使用Windows的IE浏览器。

    同样使用Applet需要客户端安装Java运行时。

    这些传统的页面刷新方式都或多或少的存在着一些确定,在Web项目应用中的使用也越来越少。

     

    2、Ajax轮询

    Ajax轮询方式是使用客户端脚本,通过XMLHttpRequest来定时发送请求,从而查询页面数据的更新情况。通过这种方式,程序实现方便简捷,但客户端频繁的发送请求会给服务器带来很大的压力和客户端处理器负载,如果服务器端没有更新时,这种轮询访问服务器便是无意义的,并且耗费了网络资源与CPU处理资源。

    实例说明:服务器端通过手动控制按钮产生一张图片,客户端显示最新图片及图片的信息内容。

    服务器端通过一个按钮btnGet产生图片,按钮事件代码如下所示。

    代码清单1:

    protected void btnGet_Click(object sender, EventArgs e)

    {

        //通过改写一张父图片上的文字来产生新图片

        System.Drawing.Image image = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath("parent.jpg"));

        string currTime = System.DateTime.Now.ToString("yyMMddHHmmssffffff");

     

        Graphics g = Graphics.FromImage(image);

        g.DrawImage(image, 0, 0, image.Width, image.Height);

        g.DrawString(currTime, new Font("Arial", 28), new SolidBrush(Color.Red), 10, 10);

        g.Dispose();

     

        string savePath = "Pic/" + currTime + ".jpg";

        image.Save(HttpContext.Current.Server.MapPath(savePath));

     

        //将最新图片文件名写入到XML文件中

        XmlDocument xmlDoc = new XmlDocument();

        xmlDoc.Load(HttpContext.Current.Server.MapPath("newPic.xml"));

        XmlNodeList nodeList = xmlDoc.SelectSingleNode("Items").ChildNodes;

     

        XmlElement element = (XmlElement)nodeList[0];

        element.SetAttribute("code", currTime);

        xmlDoc.Save(HttpContext.Current.Server.MapPath("newPic.xml"));

    }

    显示图片页面通过两个页面分别显示图片信息与图片内容,显示图片页面内容如下所示。

    代码清单2:

    <html xmlns="http://www.w3.org/1999/xhtml" >

    <head runat="server">

        <title></title>

        <meta http-equiv="Content-Type" content="text/html; Charset=gb2312" />

        <script type="text/JavaScript">

            var xmlHttp;

            function CreateXMLHttp() {

                if(window.XMLHttpRequest) {

                    xmlHttp = new XMLHttpRequest();

                }

                else if (window.ActiveXObject) {

                    try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); }

                    catch(e) {

                        try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }

                        catch(e) { }

                    }

                }

                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP.5.0");

            }

     

            function startXMLHttp() {

                CreateXMLHttp();

                xmlHttp.onreadystatechange =retDeal;

                xmlHttp.open("post","imgInfo.aspx",true);

                xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded charset=gb2312");

                xmlHttp.send();

            }       

         

             function retDeal() {

               if(xmlHttp.readystate==4) {

                 if(xmlHttp.status==200) {

                   hid1.value = xmlHttp.responseText;

                   if(hid1.value != hid2.value) {

                     hid2.value = hid1.value;

                     ifrImg.location.reload();

                     document.getElementById("Content").innerHTML = hid1.value;

                   }

                 }

                 setTimeout(startXMLHttp,2000);

              }

            }

        </script>

    </head>

    <body onload='javascript:startXMLHttp()'>

        <div></div>

        <span id="Content"></span>

        <input type="hidden" id="hid1" /><input type="hidden" id="hid2" />

        <iframe id="ifrImg" src="img.aspx" width="800" height="500"></iframe>

    </body>

    </html>

     

    3、DWR服务器Push

    DWR的反转AJAX功能允许我们从服务器端来控制客服端,而不需要客户端的请求,服务器可以自动把消息发给指定的客户端。DWR的Push技术是让服务器每次发送广播时,把这个广播推送给客户端,而不用客户端去刷新,DWR的推送是基于长连接的,性能优越。

    以服务器端通过手动控制按钮产生一张图片,客户端显示最新图片及图片的信息内容作为实例加以说明。

    服务器端通过一个按钮产生图片,页面代码如下所示。

    代码清单3:

    <%@ page language="java" pageEncoding="UTF-8"%>

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

    <title></title>

    <script type='text/javascript'src='<%=request.getContextPath()%>/dwr/interface/getPic.js'></script>

    <script type='text/javascript' src='<%=request.getContextPath()%>/dwr/engine.js'></script>

    <script type='text/javascript' src='<%=request.getContextPath()%>/dwr/util.js'></script>

    <script type="text/javascript">

        Date.prototype.format = function(format) {

        var o = {

            "M+" : this.getMonth()+1, //month

            "d+" : this.getDate(),    //day

            "h+" : this.getHours(),   //hour

            "m+" : this.getMinutes(), //minute

            "s+" : this.getSeconds(), //second

            "q+" : Math.floor((this.getMonth()+3)/3), //quarter

            "S" : this.getMilliseconds() //millisecond

            }

        if(/(y+)/.test(format)) format=format.replace(RegExp.$1,

            (this.getFullYear()+"").substr(4 - RegExp.$1.length));

        for(var k in o)if(new RegExp("("+ k +")").test(format))

            format = format.replace(RegExp.$1,

                RegExp.$1.length==1 ? o[k] :

                    ("00"+ o[k]).substr((""+ o[k]).length));

        return format;

        }

     

        function getNewPic() {

            var currTime = new Date().format("yyMMddhhmmssS");

            var currPath = "D:/Program/Java/JavaSpace/ajaxTest/WebContent/";

           getPic.createStringMark(currPath+"parent.jpg",currTime,currPath+"Pic/"+currTime+".jpg");

            getPic.getNewPicId(currTime);

            }

    </script>

    </head>

    <body>

        <input type="button" value="产生新图片" onclick="getNewPic();" />

    </body>

    </html>

    显示图片页面通过两个页面分别显示图片信息与图片内容,显示图片页面内容如下所示。

    代码清单4:

    <%@ page language="java" pageEncoding="UTF-8"%>

    <jsp:useBean id="aGetNewPic" scope="page" class="com.getNewPic" />

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

    <title></title>

    <script type='text/javascript'src='<%=request.getContextPath()%>/dwr/interface/getPic.js'></script>

    <script type='text/javascript' src='<%=request.getContextPath()%>/dwr/engine.js'></script>

    <script type='text/javascript' src='<%=request.getContextPath()%>/dwr/util.js'></script>

    <script type="text/javascript">

        function init() {

            dwr.engine.setActiveReverseAjax(true);    //激活反转

            }

        window.onload = init;//页面初始化方法

        function refreshImg() {

            ifrImg.location.reload();

            }

    </script>

    </head>

    <body>

        <div style=" float:left">最新图片:</div>

        <span id="divNewPicId"><%= aGetNewPic.currPicId %></span>

        <iframe id="ifrImg" src="img.jsp?id=<%= aGetNewPic.currPicId %>" width="800"height="500"></iframe>

    </body>

    </html>

    另外,getNewPic类用于产生新图片、Push处理。

    代码清单5:

    public class getNewPic {

          

           public static String currPicId = "100413101427820";

          

           public String getNewPicId(String picId, HttpServletRequest request){

                  if(currPicId == picId)return currPicId;

                  if(picId != null) currPicId = picId;

                 

                  //获得DWR上下文

                  ServletContext sc = request.getSession().getServletContext();

                  ServerContext sctx = ServerContextFactory.get(sc);

                  //获得当前浏览 client.jsp 页面的所有脚本session

                  Collection sessions = sctx.getScriptSessionsByPage("/ajaxTest/client.jsp");

                  Util util = new Util(sessions);

                  //处理这些页面中的一些元素

                  util.setValue("divNewPicId", currPicId);

                  util.addFunctionCall("refreshImg",null);

                 

                  return currPicId;

           }

          

           public boolean createStringMark(String filePath,String markContent,String savePath)

           {

               ImageIcon imgIcon=new ImageIcon(filePath);

               Image theImg =imgIcon.getImage();

               int width=theImg.getWidth(null);

               int height= theImg.getHeight(null);

               //System.out.println(theImg);

               BufferedImage bimage = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);

               Graphics2D g=bimage.createGraphics();

               g.setColor(Color.red);

               g.setBackground(Color.white);

               g.drawImage(theImg, 0, 0, null );

               g.setFont(new Font("Arial",Font.PLAIN,28)); //字体、字型、字号

               g.drawString(markContent,10,10); //画文字

               g.dispose();

               try

               {

                      FileOutputStream out=new FileOutputStream(savePath); //输出文件名

                      JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(out);

                      JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);

                      param.setQuality(1, true);

                      encoder.encode(bimage, param);

                      out.close();

                  }

               catch(Exception e)

               { return false; }

               return true;

           }

     

    }

     

    4、与服务端建立长连接

    与服务器建立长连接,也就是在显示数据页面中嵌入一个隐藏页面,该隐藏页面主要完成取服务器端所要显示的数据,并且将该页面显示数据的方法写成一个死循环,以此来保持与服务器端的长连接。

    同样以服务器端通过手动控制按钮产生一张图片,客户端显示最新图片及图片的信息内容作为实例加以说明。

    服务器端通过一个按钮btnGet产生图片,按钮事件代码同代码清单1。

    显示图片页面通过两个页面分别显示图片信息与图片内容,显示图片页面内容如下所示。

    代码清单6:

    <html xmlns="http://www.w3.org/1999/xhtml">

    <head runat="server">

        <title></title>

    <script type="text/javascript">

        function writePicInfo(str) {

            if (window.document.getElementById("divNewPicId").innerText != str) {

                window.document.getElementById("divNewPicId").innerText = str;

                ifrImg.location.reload();

            }

        }

        function onload(){

            var ifrpush = new ActiveXObject("htmlfile"); // 创建对象

            ifrpush.open();

            var ifrDiv = ifrpush.createElement("div"); //添加一个DIV

            ifrpush.appendChild(ifrDiv); //添加到htmlfile

            ifrpush.parentWindow.writePicInfo = writePicInfo; //注册javascript方法

            ifrDiv.innerHTML = "<iframe src='getNew.aspx'></iframe>"//在div里添加iframe

            ifrpush.close();

        }

         onload();

        </script>

    </head>

    <body>

            <div style=" float:left">最新图片:</div>

            <div id="divNewPicId"></div>

            <iframe id="ifrImg" src="img.aspx" width="800" height="500"></iframe>

    </body>

    </html>

    其中,隐藏页面getNew.aspx代码如下所示。

    代码清单7:

    protected override void Render(HtmlTextWriter output)

    {

        string str;

        while (true)  //死循环保持长链接

        {

            //读取最新图片信息

            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.Load(HttpContext.Current.Server.MapPath("newPic.xml"));

            XmlNodeList nodeList = xmlDoc.SelectSingleNode("Items").ChildNodes;

            XmlElement element = (XmlElement)nodeList[0];

            string newPicId = element.GetAttribute("code");

     

            str = "<script >window.parent.writePicInfo('" + newPicId + "')</script>";

            this.Context.Response.Write(str);

            this.Context.Response.Flush();

            System.Threading.Thread.Sleep(2000);

        }

    }

    代码中的“htmlfile”是一个类似JavaScript中Window对象的一个ActiveX Object,它内部也是DOM结构,将作为隐藏帧的IFrame写入这个对象中,这样可以解决进度条一直为读取状态的问题。

     

    5、RTMP协议传输

    随着网络技术的迅猛发展,视频、音频等多媒体通信需求越来越多,Adobe公司开放了RTMP(the Real-time Messaging Protocol)协议规范,RTMP协议作为客户端和服务器端的传输协议,这是一个专门为高效传输视频、音频和数据而设计的TCP/IP 协议。其优秀产品Flex是用于构建和维护在所有主要浏览器、桌面和操作系统一致地部署的极具表现力的 Web 应用程序的高效率的开放源码框架。

    从目前的应用来说,RTMP主要用于音、视频的传输,流视频服务器就是FMS(Flash Media Server),其原称为FCS(Flash Communication Server),技术范畴能应用到诸如Flash聊天室、视频会议等领域。

    以一个实现聊天功能的Flex程序为例,显示聊天内容代码如下所示。

    代码清单8:

    <?xml version="1.0" encoding="utf-8"?>

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12" creationComplete="init()">

     

    <mx:Script>

        <![CDATA[

       

        import vo.Message;

        import mx.collections.ArrayCollection;

        import mx.controls.Alert;

       

        private var myNetConnection:NetConnection;  //flex fms 链接用的对象

        private var serverApp:String ="rtmp://127.0.0.1/Test";

        private var talk_so:SharedObject;  //fms 下的SharedObject 对象

          

        private function init():void

        {

           btn_send.addEventListener(MouseEvent.CLICK,btnSenClickHandler);

           myNetConnection = new NetConnection();

           myNetConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);   

           myNetConnection.connect(serverApp);

        }

       

        private function netStatusHandler(evt:NetStatusEvent):void

        {

           trace(evt.info.code);  //调试代码用     

           if ( evt.info.code =="NetConnection.Connect.Success" )

           {

               talk_so = SharedObject.getRemote("talk",myNetConnection.uri,true);

               talk_so.addEventListener(SyncEvent.SYNC,talkSoSyncHandler);

               talk_so.connect(myNetConnection);

           }

           else

           {

               Alert.show("链接失败"+evt.info.code);

           }

        }

       

        private function talkSoSyncHandler(evt:SyncEvent):void

        {

           txt_content.text="";

           if ( talk_so.data.msgList!=null )

           {

               var tmp:ArrayCollection = new ArrayCollection();

               convertArrayCollection(tmp,talk_so.data.msgList as ArrayCollection);        

               for(var i:int=0;i<tmp.length ;i++)

               {

                  var message:Object = tmp.getItemAt(i);          

                  varfullMsg:String=message.nickname+""+message.time.toTimeString()+":"+message.msg;          

                  txt_content.text=txt_content.text+fullMsg+"/n";

               }

           }

        }

          

        private function btnSenClickHandler(evt:MouseEvent):void

        {

           var arr:ArrayCollection = new ArrayCollection();    

           if ( talk_so.data.msgList==null )

           {

               arr = new ArrayCollection();   

           }

           else

           {

               convertArrayCollection(arr,talk_so.data.msgList as ArrayCollection);

           }     

           var obj:Message = new Message();

           obj.nickname=txt_nickname.text;

           obj.msg=txt_message.text;

           obj.time = new Date();     

           arr.addItem(obj);   

           talk_so.setProperty("msgList",arr);

           /*将你更新好的聊天记录列表写入到公共的SharedObject对象中去即可。

               调用setProperty() 以更改数据对象的属性。 服务器将更新这些属性,并调度 sync 事件,并将这些属性发回到连接的客户端。*/

           txt_message.text="";

        }

       

        //交换数组中元素

        private functionconvertArrayCollection(arrNew:ArrayCollection,arrOld:ArrayCollection):void

        {

           arrNew.removeAll();     

           for(var i:int=0;i<arrOld.length ;i++)

           {

               arrNew.addItemAt(arrOld.getItemAt(i),i);

           }

        }     

        ]]>

    </mx:Script>

     

        <mx:TextArea x="33" y="10" height="159" width="366" id="txt_content"/>

        <mx:TextInput x="33" y="177" width="62" id="txt_nickname"/>

        <mx:Label x="103" y="179" text=""/>

        <mx:TextInput x="146" y="177" width="185" id="txt_message"/>

        <mx:Button x="334" y="177" label="send" id="btn_send"/>

       

    </mx:Application>

     

    三、结语

    从目前实际应用来说,以上四种实现Web页面实时刷新都是可行方案,各有优缺点与适用的具体环境。

    Ajax轮询方式比较适用于需要传输的数据量较小的情况,可通过客户端首先轮询服务器端的更新标识,若有更新再下载更新数据,这样能减小一部分服务器的压力。

    DWR反转AJAX功能,真正实现了从服务器端将更新“推”到客户端。

    与服务器端建立长连接的方式,也是通过客户端的请求获取更新数据的。

    通过RTMP协议传输,主要适用于音、视频的数据传输,比较适用于视频聊天室,目前视频服务器FMS的费用较高(4500元100个客户端),与服务器的连接数受到限制。

    总体来看,要实现Web页面的实时刷新,肯定是会给服务器带来一定的压力的,对于具体项目的不同需求,可选择合适的方式来实现Web页面的实时刷新。


    展开全文
  • web worker实时刷新界面执行次数

    千次阅读 2018-09-13 16:52:30
    看了一大顿web worker 唯一的意识可能就是当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。...所以在前台为了实时刷新执行次数,就用webwork写了个代码,刷新的是bootstra...

    看了一大顿web worker 唯一的意识可能就是当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时web worker 在后台运行。
    所以在前台为了实时刷新执行次数,就用webwork写了个代码,刷新的是bootstrap table中的数据
    1、js代码

    window.onload =setInterval(function(){
                var allTableData = $("#table").bootstrapTable('getData');//获取表格的所有内容行
                   //向后台线程提交随机数组
    
                   worker.postMessage(JSON.stringify(allTableData));
                   //从线程中取得计算结果
                   worker.onmessage=function(event){
                        if(event.data!=null){
                            var jsonObj =  JSON.parse(event.data);
                            for(var k in jsonObj){
                            //此处为解析后台传过来的对象,放到row对象中
                            var row  = {
                                index:**,
                                field:**,
                                value:**,
                                };//可以查看一下datatable的updateCell需要的参数
                             };
                             //更新表格数据        
                            $('#table').bootstrapTable("updateCell",rows);
                            }
                        }
                   };
            },3000);

    2、webworker.js代码

    onmessage=function(event){
    var data=event.data;
    if(data!=null){
        var jsonObj = eval(data);
        var resStr ;
        var request = new XMLHttpRequest();//weworker只能用XMLHttpRequest,不能用$ajax,因为webworker不会识别全局变量,具体的可以看看解释
        //GET的参数要写在URL中,不在send中写
        request.open("POST", "../user/updataUser?jsonObj ="+jsonObj );
        request.send(null);
        request.onreadystatechange = function() {
            if(request.readyState === 4) { //readyState为4表明服务器请求已结束
                if(request.status === 200) { //判断请求是否成功
                    resStr = request.responseText;
                    postMessage(resStr);
                } 
            }
        }
    
    }
    };

    3、webwork的一些解释
    Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。

    Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

    Web Worker 有以下几个使用注意点。

    (1)同源限制

    分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

    (2)DOM 限制

    Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。

    (3)通信联系

    Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

    (4)脚本限制

    Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

    (5)文件限制

    Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

    更多解释以及方法可以查看http://www.ruanyifeng.com/blog/2018/07/web-worker.html

    展开全文
  • web开发对实时刷新的需求 在刚开始学习前端时每次修改文件内容后都需要手工刷新下浏览器来看效果,做的次数多了就特别难受,有时仅仅修改了一个字母都需要刷新下页面查看 之后接触到编写边看的集成IDE,文件修改保存...

    web开发对实时刷新的需求

    在刚开始学习前端时每次修改文件内容后都需要手工刷新下浏览器来看效果,做的次数多了就特别难受,有时仅仅修改了一个字母都需要刷新下页面查看

    之后接触到编写边看的集成IDE,文件修改保存后就可以实时显示效果,用起来还不错,但有个问题就是IDE里面一般都是内嵌的一个浏览器,与常用的浏览器还是有许多区别的

    browser sync的功能:

    Browsersync能让浏览器实时、快速响应您的文件更改(html、js、css、sass、less等)并自动刷新页面。更重要的是 Browsersync可以同时在PC、平板、手机等设备下进项调试。您可以想象一下:“假设您的桌子上有pc、ipad、iphone、android等设备,同时打开了您需要调试的页面,当您使用browsersync后,您的任何一次代码保存,以上的设备都会同时显示您的改动”。无论您是前端还是后端工程师,使用它将提高您30%的工作效率。

    最吸引人的莫过于多屏同步,可以在不同浏览器里打开,操作在一个浏览器里的操作同时会映射到另一个浏览器;
    在有一个就是多终端同步:同时可以使用手机查看效果且操作和PC端打开的是同步

    安装 browser sync

    browser sync需要nodejs,在自己PC上安装nodejs nodejs下载地址nodejs
    windows用户可以打开命令行,查看nodejs是否安装, node -v
    node官网下载速度比较版,node安装好后使用淘宝镜像安装工具
    npm install -g cnpm --registry=https://registry.npm.taobao.org
    现在可以使用npm来安装了
    cnpm install browser-sync -g

    启动browsersync
    browser-sync start --server files "path/to/file, path/to/another/file"
    对于使用thinkphp框架的话建议弄个配置文件,假设为 bs-config.js

    /
    |--------------------------------------------------------------------------
    | Browser-sync config file
    |--------------------------------------------------------------------------
    |
    | For up-to-date information about the options:
    | http://www.browsersync.io/docs/options/
    |
    | There are more options than you see here, these are just the ones that are
    | set internally. See the website for more info.
    |
    |
    /
    var root = "./Application/Home/";
    var cssUrl = root + "Public/css/";
    var jsUrl = root + "Public/js/";
    var html = root + "View/";
    module.exports = {
    "ui": {
    "port": 3001,
    "weinre": {
    "port": 8080
    }
    },
    "files": [
    cssUrl + "class/.css",
    jsUrl + "class/
    .js",
    html + "class/*.html"
    ],
    "watchEvents": [
    "change"
    ],
    "watchOptions": {
    "ignoreInitial": true
    },
    "server": false,
    "proxy": "localhost",
    "port": 80,
    "middleware": false,
    "serveStatic": [],
    "ghostMode": {
    "clicks": true,
    "scroll": true,
    "forms": {
    "submit": true,
    "inputs": true,
    "toggles": true
    }
    },
    "logLevel": "info",
    "logPrefix": "BS",
    "logConnections": false,
    "logFileChanges": true,
    "logSnippet": true,
    "rewriteRules": [],
    "open": "local",
    "browser": "default",
    "cors": false,
    "xip": false,
    "hostnameSuffix": false,
    "reloadOnRestart": false,
    "notify": true,
    "scrollProportionally": true,
    "scrollThrottle": 0,
    "scrollRestoreTechnique": "window.name",
    "scrollElements": [],
    "scrollElementMapping": [],
    "reloadDelay": 0,
    "reloadDebounce": 0,
    "reloadThrottle": 0,
    "plugins": [],
    "injectChanges": true,
    "startPath": null,
    "minify": true,
    "host": null,
    "localOnly": false,
    "codeSync": true,
    "timestamps": true,
    "clientEvents": [
    "scroll",
    "scroll:element",
    "input:text",
    "input:toggles",
    "form:submit",
    "form:reset",
    "click"
    ],
    "socket": {
    "socketIoOptions": {
    "log": false
    },
    "socketIoClientConfig": {
    "reconnectionAttempts": 50
    },
    "path": "/browser-sync/socket.io",
    "clientPath": "/browser-sync",
    "namespace": "/browser-sync",
    "clients": {
    "heartbeatTimeout": 5000
    }
    },
    "tagNames": {
    "less": "link",
    "scss": "link",
    "css": "link",
    "jpg": "img",
    "jpeg": "img",
    "png": "img",
    "svg": "img",
    "gif": "img",
    "js": "script"
    }
    };

    修改下配置文件里的files选项,修改为你自己的css,js文件所在位置
    启动是使用如下命令:browser-sync start --config bs-config.js

    注:当你修改相应的css,js文件后浏览器里未刷新那可能是配置里有问题,比如监控路径出错等等

    转载于:https://www.cnblogs.com/scarecrowlxb/p/6659910.html

    展开全文
  • 想用网页制作例如轨迹实时更新,用线表现运动轨迹,.net。哪位大神帮帮忙,谢谢了
  • 前端绘制了表格,表格内的数据实时刷新。 目前用的Websocket,每秒推送2次,每次数据量大概在1MB,表格大概有400行4列,也就是有1600个数值需要每秒刷新2次。 服务端很好,完全无压力,但客户端浏览器很卡,求解。...
  • web开发中常常会遇到前后端通信的情况出现,甚至是双向通信,类似于聊天室的功能,那么今天的主角就是Socket.IO什么是Socket.IO?官网:https://socket.io/github地址:https://github.com/socketio/socket.io其他...
  • 实时刷新web的整体思路:当点击分支显示时,做的操作是,把服务名发送到后端,然后调用shell执行git相关命令的操作,将所有分支实时显示到web界面上,然后通过点击触发事件将分支名加到vuex中对应的服务名后面的...
  • 1、 创建一个MVC项目 SignalRDemo 2、 使用”管理NuGet程序包”添加Signalr相关的引用. Microsoft.AspNet.SignalR 安装相关dll和js ...6、 在Web应用程序启动或者停止时,开始或者停止SqlServ...
  • web显示实时时间动态刷新

    千次阅读 2017-09-05 16:28:52
    代码如下: ; charset=utf-8" /> <title></title> <script type="text/javascript" src="jquery/jquery.min.js"></script> <script type="text/javascrip
  • 我们新建一个http://localhost:5000的WebApi用于身份认证,再新建一个http://localhost:5001的客户端,首先点击【模拟登录获取Toen】获取访问令牌和刷新令牌,然后点击【调用客户端获取当前时间】,如下:接下来我们...
  • vue websocket 实现页面实时刷新

    千次阅读 2019-09-05 10:33:37
    最近公司项目需求后台web端要做实时能看到用户的登录状态以及所在位置,说白了就是要做数据实时刷新。 直接上代码吧! <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> ...
  • Web实时通信技术

    千次阅读 2016-08-19 21:11:41
    本周在应用宝前端分享会上分享了Web实时通信技术,分享内容整理如下。一、传统Web数据更新传统的Web数据更新,必须要刷新网页才能显示更新的内容。这是浏览器采用的是B/S架构,而B/S架构是基于HTTP协议的。HTTP协议...
  • 传统的web通信模式,后台处理数据,需要一定时间,前端想要知道后端的处理结果,就要不定时的向后端发出请求以获得最新情况。 2. 应用场景:小型应用 3. 优点:前后端编写程序容易 4. 缺点: 1、请求中有大半是
  • 现有一个业务需要将后台中启动的某个bat批处理文件所打印的内容实时的在web前端界面进行展示。 后台启动cmd使用的是 Process process = Runtime.getRuntime().exec("cmd /c start F:\\test.bat"); 方式, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 809
精华内容 323
关键字:

web实时刷新