ajax实现长连接

Posted 傻子没有烦恼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ajax实现长连接相关的知识,希望对你有一定的参考价值。

项目需求:需要实时的读取日志文件里的数据,并且使用Echart实时更新折线图。

使用ajax实现客户端与服务器端的数据传输。

目的:我想通过ajax与服务器建立一个长连接,服务器会不断的传输数据给前台,由于日志不断的更新,我想把新的数据不断的传给前台。

设计:本来想着使用服务器使用一个死循环去读取日志信息,一个线程去提交数据。

参考:https://www.cnblogs.com/hoojo/p/longPolling_comet_jquery_iframe_ajax.html

发现与想象的不同,这个长连接并不是不间断的连接,而是连接成功一次,传输完数据断开,再重新建立新连接,会重新去调用函数。

由于一开始的理解错误,因为用死循环去读取日志,这样会导致每次都会调用一次函数,这样会开启多个死循环,打开任务管理器,发现CPU和内存的不断飙升,所以每次连接都要跳出死循环。

这样会产生新问题,每次都要重新读日志。

设计,保存上一次读取的位置,避免重头开始。

前台代码:

//异步请求获取数据,递归调用自己,实现长连接
           
function longPolling() {
    $.ajax({
        type:\'POST\',
        url:\'get\',
        dataType:\'json\',
        data:postData,
        timeout: 20000,
        success:function(result){
            if(result){
                //保存文件指针,再传给后台                
                postData.lastTimeFileSize = result.pointer    
                //添加数据
                for(var i=0;i<result.axis.length;i++){
                    datax.push(result.axis[i]);
                    datay.push(result.series[0].data[i]);
                }
                //画图
                myChart.hideLoading();
                myChart.setOption({
                     xAxis: {
                         data: datax
                     },
                     series: [{
                         // 根据名字对应到相应的系列
                         name: \'alpha.water\',
                         data: datay
                     }]
                }); 
                
                longPolling();
            }
         },
        error:function(XMLHttpRequest, textStatus, errorThrown){            
            console.error("加载数据失败");                    
            longPolling();        
        },
                    
    });
    
};

后台代码:

发送数据


public class getData extends HttpServlet {
File logFile = new File("D:\\\\workspace\\\\drawChart\\\\src\\\\read_log\\\\log.txt");
private long lastTimeFileSize = 0; // 上次文件大小


//
打包数据为Json格式传给前台 public void pickData(HttpServletRequest request,HttpServletResponse response,Float message[][],long pointer) throws ServletException, IOException { List<String> legend = new ArrayList<String>(Arrays.asList(new String[]{"alpha.water"})); //x轴时间 List<Float> axis = new ArrayList<Float>(Arrays.asList(message[0])); List<Series> series=new ArrayList<Series>(); //series series.add(new Series("alpha.water","line",new ArrayList<Float>(Arrays.asList(message[1])))); //更改下一行代码,添加多个series Echarts echarts = new Echarts(legend,axis,series,pointer); ObjectMapper objectMapper = new ObjectMapper(); String str = objectMapper.writeValueAsString(echarts); System.out.println(objectMapper.writeValueAsString(echarts)); response.setContentType("text/html;charset=utf-8"); //发送数据 PrintWriter out = response.getWriter(); out.write(str); System.out.println("发送post方法。。。。。。。。。。"); out.flush(); out.close(); }

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{
        String regEx = "(-?\\\\d+)(\\\\.\\\\d+)?";
        String regEx0 = "^Time = [0-9]\\\\d*\\\\.\\\\d*|0\\\\.\\\\d*[1-9]\\\\d*$";                
        Pattern pattern = Pattern.compile(regEx);
        Pattern pattern0 = Pattern.compile(regEx0);
        float alpha = 0;
        float p_rgh = 0;
        float omega = 0;
        float k = 0;
        float DTime = 0;
        //用来保存所有数据的二维数组
        Float message[][] = new Float[14][5];    
        //计数器,个数据传一次
        int flag = -1;        
        //获取保存的上一次读取的位置
        String str = request.getParameter("lastTimeFileSize");        
        lastTimeFileSize = Long.parseLong(str);
        System.out.println(lastTimeFileSize);          
                 
        try {
            long len = logFile.length();
            System.out.println(len);
            if(lastTimeFileSize >= len){
                lastTimeFileSize = len;
                try {
                    //如果读取的速度超过写的速度,等待5秒
                    Thread.sleep(5000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }                              
            }else{
                 RandomAccessFile randomFile = new RandomAccessFile(logFile, "r");     
                 randomFile.seek(lastTimeFileSize);                    
                 String tmp = null;                                                                 
                 while ((tmp = randomFile.readLine()) != null) {                                                                       
                     //正则匹配时间                                           
                     Matcher matcher0 = pattern0.matcher(tmp);
                     if(matcher0.lookingAt()){                               
                         if(flag==4){                                
                            //记录读取文件的位置
                            lastTimeFileSize = randomFile.getFilePointer();
                            System.out.println(lastTimeFileSize);
                            //传数据                                
                             try {
                                Thread.sleep(3000);
                                //由于是根据time决定是否提交,所以提交5次需要读6个time,文件指针会只在time后面,因此要倒回
                                lastTimeFileSize -= 50;
                                pickData(request,response,message,lastTimeFileSize);
                                
                            } catch (InterruptedException e1) {
                                e1.printStackTrace();
                            }  
                            randomFile.close();
                            flag = -1;
                            break;
                         }                         
                         DTime = Float.parseFloat(tmp.split("=")[1]);                                                     
                         flag++;
                         message[0][flag] = DTime;                            
                     }
                     //yangmo
                     //找到 alpha p_rgh Omega k;
                     else if((tmp.startsWith("smoothSolver:  Solving for alpha.water")))
                     {
                         String[] splitAddress = tmp.split(",")[1].split("=");                         
                         alpha = Float.parseFloat(splitAddress[1]);  
                         System.out.println(flag);
                         message[1][flag] = alpha;  
                         //System.out.println(alpha);
                         
                     }
                     else if((tmp.startsWith("GAMG:  Solving for p_rgh")))
                     {
                         String[] splitAddress = tmp.split(",")[1].split("=");                             
                         p_rgh = Float.parseFloat(splitAddress[1]);
                         message[2][flag] = p_rgh;
                         //System.out.println(p_rgh);
                     }
                     else if((tmp.startsWith("smoothSolver:  Solving for omega")))
                     {
                         String[] splitAddress = tmp.split(",")[1].split("="); 
                         omega = Float.parseFloat(splitAddress[1]);
                         message[3][flag] = omega;
                         //System.out.println(omega);
                     }
                     else if((tmp.startsWith("smoothSolver:  Solving for k")))
                     {
                         String[] splitAddress = tmp.split(",")[1].split("="); 
                         k = Float.parseFloat(splitAddress[1]);
                         message[4][flag] = k;
                         //System.out.println(k);
                     }
                     //找到 x,y,z
                     else if(tmp.equals("Sum of forces"))
                     {
                         int j = 5;
                         for(int i=1;i<=3;i++){                              
                             String line = randomFile.readLine();                                                              
                             Matcher matcher = pattern.matcher(line); 
                             //正则匹配数值
                             while(matcher.find()){                                 
                                 message[j][flag] = Float.parseFloat(matcher.group());
                                 j++;
                             }                                                                                                 
                         }                           
                     }                        
                 } 
                 //读到文件的末尾需要把剩余数据的提交
                 if(flag>-1){
                     //提交最后的数据
                     lastTimeFileSize = randomFile.getFilePointer();
                     lastTimeFileSize -= 50;
                     pickData(request,response,message,lastTimeFileSize);
                 }else
                 {
                     //等待,可以有效的避免前台无间歇的询问导致CPU占用增大
                     try {                        
                         Thread.sleep(10000);
                     } catch (InterruptedException e1) {
                         e1.printStackTrace();
                     }                        
                 }
            }           
        } catch (IOException e) {               
            e.printStackTrace();
        }finally{
            //其它操作            
        }         
    }  
}

 

 

红色标记内容是相关内容

注意:类中如果使用构造器去传递文件的路径名,则ajax请求会失败

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<servlet>
<description></description>
<display-name>getData</display-name>
<servlet-name>getData</servlet-name>
<servlet-class>read_log.getData</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getData</servlet-name>
<url-pattern>/get</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>chart.jsp</welcome-file>
</welcome-file-list>
</web-app>


以上是关于ajax实现长连接的主要内容,如果未能解决你的问题,请参考以下文章

html PHP代码片段: - AJAX基本示例:此代码演示了使用PHP和JavaScript实现的基本AJAX功能。

http长连接总结

http长连接总结

如何在页面离开时终止长轮询 Ajax 请求

nginx配置长连接(ajax60秒请求超时)

nginx配置长连接(ajax60秒请求超时)