comet基于长连接流实现服务器端反向推数据的方式

2019-03-03 13:15|来源: 领悟书生

comet用来解决服务器端反向推数据

目前有多种方式可以实现

1.长连接

   基于长连接流的方式

   基于长轮询的方式

2.websocket


这一节我们说基于长连接流的方式实现服务端反向推数据


1.修改tomcat,让其可以支持NIO方式

直接修改server.xml里的Connector节点,修改protocol为org.apache.coyote.http11.Http11NioProtocol

<Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"  redirectPort="8443" />


2.创建servlet,让其实现org.apache.catalina.CometProcessor

不用实现doGet()和doPost()

package com.naxsu.comet.servlet;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;
 
public class SecondServlet extends HttpServlet implements CometProcessor {
    private static final long serialVersionUID = 1L;
 
    public void event(CometEvent event) throws IOException{
        /*
         * event方法用来处理各种请求,可以根据状态的不同得到各种响应
         * 同时可以不断根据自己的需求像客户端发送信息
         */
        HttpServletResponse resp = event.getHttpServletResponse();
        HttpServletRequest req = event.getHttpServletRequest();
        //对于event而言,会存在多种状态,在begin的时候可以开始获取数据
        if(event.getEventType()==CometEvent.EventType.BEGIN) {
            System.out.println(req.getSession().getId());
            //在begin的状态进行数据写操作
            log(req.getSession().getId()+"连接建立成功");
            new Thread(new RandomThread(resp)).start();
        } else if(event.getEventType()==CometEvent.EventType.END) {
            //请求结束的时候执行
            log(req.getSession().getId()+"已经结束");
            event.close();
        } else if(event.getEventType()==CometEvent.EventType.ERROR) {
            //发送错误的时候处理
            log(req.getSession().getId()+"发送错误");
            event.close();
        } else if(event.getEventType()==CometEvent.EventType.READ) {
            //还正读取数据的状态
            throw new RuntimeException("该状态无法进行操作");
        }
    }
 
    @Override
    public void init() throws ServletException {
        super.init();
    }
}

在建立连接成功的时候,用到一个线程类,来维护数据的反推

package com.naxsu.comet.servlet;
 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;
 
import javax.servlet.http.HttpServletResponse;
 
public class RandomThread implements Runnable {
    private final static Random ran = new Random();
    private boolean running = true;
    private HttpServletResponse connect;
 
    public RandomThread(HttpServletResponse connect) {
    this.connect = connect;
    }
     
    @Override
    public void run() {
    while(running) {
            try {
        Thread.sleep(5000);
        PrintWriter out = connect.getWriter();
        int num = ran.nextInt(100);
        System.out.println("send:"+num);
        /*
         *基于流的方式由于整个过程仅仅用一个连接,所以全部都使用同一个
         *response来进行传递,所以不能关闭流
         */
        out.println(num+"");
        //必须刷新
        out.flush();
        } catch (InterruptedException e) {
        e.printStackTrace();
        } catch (IOException e) {
        e.printStackTrace();
        }
    }
    }
}


3.页面发起请求进行连接,服务器不断的向页面抢着数据


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>基于长连接流的方式实现</title>
<script type="text/javascript" src="js/jquery-1.9.0.js"></script>
<script type="text/javascript">
$(function(){
    var xhr = createXmlHttpRequest();
    xhr.open("POST","second.do",true);
    //由于jquery没有办法支持不同的状态码的判断,所以需要通过原始的ajax来处理
    var pos = 0;
    xhr.onreadystatechange = function() {
        //让状态码等于3就可以保证两端一直进行连接,这是实现长连接的stream的方式
    if(xhr.readyState==3&&xhr.status==200) {
        //获取相应的文本:通过xhr的responseText可以获取文本信息,包括xml的标签
        //通过responseXML可以获取xml的信息,只能xml对象
        $("#content").append(xhr.responseText.substring(pos)+",");
        pos = xhr.responseText.length;
    }
    };
    xhr.send();
});
 
function createXmlHttpRequest() {
    if(window.XMLHttpRequest) {
    //针对其他主流浏览器
    return new XMLHttpRequest();
    } else if(window.ActiveXObject) {
    //针对IE5和IE6
    return new ActiveXObject("Microsoft.XMLHTTP");
    } else {
    alert("你使用的浏览器不支持XMLHttpRequest,请换一个浏览器再试!");
    return null;
    }
}
</script>
</head>
<body>
<div id="content"></div>
</body>
</html>

页面效果如下:



也许你发现:google浏览器是不支持的

原因:

   基于长连接的方式,由于状态码是在3的时候出来数据,对于很多浏览器而言并不支持在状态为处理中的时候传数据,所以,限制很大。

   所以需要使用新的方式:长轮询的方式,这种方式,是目前使用最多的方式


本文链接:comet基于长连接流实现服务器端反向推数据的方式,由领悟书生原创

转载请注明出处【http://www.656463.com/article/364】

相关问答

更多
  • 用的是tcp传输还是UDP传输。和前面说的一样,socket通信传的byte,传输方法一样,都是outputStream,只是接受不一样,你只要用inputStream写成file就可以了。 没传完的话,理论上是可以显示部分数据的,看看现在浏览器的图片预览,lazy load就知道了。六帧是代表6张图么?如果是的话,你可以看网络传输速度和文件大小。
  • 你写的程序放在服务器电脑上运行,叫做服务器端编程。 既然是叫做服务器,也说明你写的程序要可以接受客户端的互动。 你写的程序放在客户端上运行,叫做客户端编程。
  • 少上搜搜上搜搜上搜搜上搜搜上搜搜
  • 用的是tcp传输还是UDP传输。和前面说的一样,socket通信传的byte,传输方法一样,都是outputStream,只是接受不一样,你只要用inputStream写成file就可以了。 没传完的话,理论上是可以显示部分数据的,看看现在浏览器的图片预览,lazy load就知道了。六帧是代表6张图么?如果是的话,你可以看网络传输速度和文件大小。
  • 服务端和普通的servlet获得数据没有区别,就是通过request.getParameter()等API获得数据. 要知道: 服务端的代码与你是通过HttpClient请求还是浏览器请求都没有联系!
  • 什么是服务器端[2022-05-02]

    简单的说,服务器端是为客户端服务的,服务的内容诸如向客户端提供资源,保存客户端数据等等.客户端可以是任意的一台电脑,只要它和服务器端存在连接,并且得到了服务器端的授权,就可以使用服务器端的服务.象现在就可以理解为百度的网站是服务器端,我们现在使用的电脑就是客户端.我们可以使用它的服务. 通常的服务器端都是服务器级的高级PC,以便多客户访问时不会造成延时甚至数据溢出.
  • 您可以使用开源的JWebSocket和基于HTML 5规范的服务器端推送的websocket。希望您可以查看http://jwebsocket.org/ 。 希望对你有帮助 you can use JWebSocket which is open source and websocket that will do server side push based on HTML 5 specification.Hope please check this link http://jwebsocket.org/. ...
  • 只要小心选择(没有冲突的端口等),使用的端口号就没有必要。 真正的问题是处理跨域请求。 由于端口在技术上位于另一台服务器上,因此我们面临跨域请求的问题。 因此,使用不同的端口号不是一个很好的解决方案。 事实证明反向代理并不像我想象的那样可怕,我只是将以下几行添加到htaccess: ProxyRequests Off ProxyPass /comet http://localhost:8888 ProxyPassReverse /comet http://localhost:8888 8888是我使用的 ...
  • 扭曲非常强大但不易使用,特别是对于新手。 tornado是Python中的另一个异步服务器,不如Twisted通用(例如,你不会将它用于网络客户端 ),但更容易用于实现服务器,包括Comet服务器。 Twisted is very powerful but not easy to use, especially for a newbie. tornado is another async server in Python, less general than Twisted (you would not u ...
  • 我是一个渐进式学习者,所以当学习新技术时,我更喜欢用我已经知道的语言(反之亦然,尝试用新语言熟悉的东西),但是,嘿,有时我们需要大爆炸...... 您没有说明您已经知道的语言和编程模型。 Comet的本质分为三个部分: 在一段时间内增量生成一些数据 通过长时间连接提供数据的服务器功能 客户端能够请求数据并从长时间连接读取 通过以下方式向后工作: 客户端你可能是基于浏览器的,因此使用JavaScript。 如果您可以使用库来处理交付,那么服务器端可以节省大量工作。 有很多选择,我在Java工作,App Ser ...