• Java_模拟comet的实现


    本文没有使用任何comet服务器, 只是利用tomcat模拟实现了一下comet, 不是真正的comet哦,因为不会有这样的应用场景, 只是模拟实现, 仅供参考.

    一. 需求.

    实现将服务端的时间推送到客户端, 客户端在得到服务端相应后将时间显示在页面上.

    二.实现.

    1开发框架: 用jsp+servlet的方法, 用了一个webframework框架, 自己写的, 类似于struts2, 可以的话就把它当作struts2来看吧.

    2. jsp代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
     
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
         
        <title>My JSP 'serverTime.jsp' starting page</title>
         
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">   
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
        <script type="text/javascript">
            var stop=false;
            var div= "";
             
            var inited = false;
            function init(){
                div = document.getElementById("forDisplay");
            }
             
            function stoped(){
                stop=true;
            }
             
            function started(){
                if(!inited){
                    init();
                    inited = true;
                }
                stop=false;
                clear();
                ajax();
            }
            function clear(){
                if(div){
                    div.innerHTML="";
                }
            }
             
            function creatXHR(){
                var xmlhttp_request = "";
                     
                  try{
                        if( window.ActiveXObject ){
                            for( var i = 5; i; i-- ){
                                try{
                                    if( i == 2 ){
                                        xmlhttp_request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
                                    else{
                                        xmlhttp_request = new ActiveXObject( "Msxml2.XMLHTTP." + i + ".0" );
                                        xmlhttp_request.setRequestHeader("Content-Type","text/xml");
                                        xmlhttp_request.setRequestHeader("Charset","gb2312"); }
                                    break;
                                }
                                catch(e){
                                    xmlhttp_request = false;
                                }
                            }
                        }
                      else if( window.XMLHttpRequest ){
                            xmlhttp_request = new XMLHttpRequest();
                        }
                    }
                  catch(e){
                        xmlhttp_request = false;
                    }
                    return xmlhttp_request;
                }
            function ajax(){
                var xmlhttp_request = creatXHR();
              xmlhttp_request.open('GET', 'ajax.action', true);
              xmlhttp_request.send(null);
              xmlhttp_request.onreadystatechange = function(){
                  if (xmlhttp_request.readyState == 4) {
                        if(xmlhttp_request.status == 200){
                          var timeStr = xmlhttp_request.responseText;
                          div.innerHTML =timeStr+"<br/>"+div.innerHTML;
                        }
                        if(!stop){
                            ajax();
                        }
                  }
              }
      
            }
        </script>
      </head>
       
      <body>
            <button value="start" onclick="started()">Start</button> <button value="stop" onclick="stoped()">Stop</button> <BR/>
            <div id="forDisplay"></div>
      </body>
    </html>

    前面我有篇文章谈到, 客户端做的事情很简单, 就是提交ajax请求, 等待服务端返回数据, 展示完后继续请求即可. 我这里做了个控制, 可以自由停止.

    3.服务端代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    package org.jiacheo.webframework.test;
     
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Random;
     
    import org.jiacheo.web.framework.Template;
    import org.jiacheo.web.framework.context.TemplateContext;
     
    public class Time4Ajax implements Template {
     
        @Override
        public String execute() {
            try {
                PrintWriter writer =TemplateContext.getResponse().getWriter();
                Random random = new Random();
                int second = random.nextInt(10);
                iambusy(second);
                Date date = new Date();
                SimpleDateFormat format = new SimpleDateFormat("服务器时间是:yyyy年MM月dd日,HH时mm分ss秒");
                System.out.println(format.format(date));
                writer.println(format.format(date));
                writer.flush();
                writer.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
             
             
            return null;
        }
     
        private void iambusy(int second) {
            // TODO Auto-generated method stub
            final int oneSecond = 1000;
            try {
                Thread.sleep(oneSecond*second);
            } catch (InterruptedException e) {
                //ignore it
            }
        }
     
    }

    每次请求都随机sleep几秒, 模拟在处理事务, 得到处理完了再返回数据, 也就是吧服务端的时间推送到客户端去.

    这样就可以模拟comet的实现了. 但这里跟comet最大的不同是, 服务端不是主动主动阻塞的, 如何做到服务端主动阻塞, 等待有了返回结果再返回给客户端, 这个服务端实现的一个难点.我之前提到可以用时间模型, 但是事件模型能做的东西实在太少了, 要是能从规范上搞定, 那这个实现就方便很多了.

    测试结果:

    客户端显示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    服务器时间是:20101125日,221919
    服务器时间是:20101125日,221910
    服务器时间是:20101125日,221907
    服务器时间是:20101125日,221906
    服务器时间是:20101125日,221904
    服务器时间是:20101125日,221900
    服务器时间是:20101125日,221852
    服务器时间是:20101125日,221848
    服务器时间是:20101125日,221839
    服务器时间是:20101125日,221835
    服务器时间是:20101125日,221828

    服务端显示

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    服务器时间是:20101125日,221828
    服务器时间是:20101125日,221835
    服务器时间是:20101125日,221839
    服务器时间是:20101125日,221848
    服务器时间是:20101125日,221852
    服务器时间是:20101125日,221900
    服务器时间是:20101125日,221904
    服务器时间是:20101125日,221906
    服务器时间是:20101125日,221907
    服务器时间是:20101125日,221910
    服务器时间是:20101125日,221919

    注意我故意将客户端倒过来显示的.  可以看到, 客户端和服务端的数据是完全一致的.

    comet, 比想想中的要难搞多了, 我能不能做个框架出来搞定他?
    关于comet 框架和服务器, 可以看看 APE(ajax push engine)

  • 相关阅读:
    100——第9例
    100——第8例
    100——第7例
    POJ
    POJ
    POJ
    Egyptian Collegiate Programming Contest 2017 (ACM ECPC 2017)
    SCUT
    SCUT
    SCUT
  • 原文地址:https://www.cnblogs.com/gisblogs/p/4269638.html
Copyright © 2020-2023  润新知