Tomcat和Jetty对WebSocket的支持

公司项目需要,了解了下目前几种支持WebSocket的框架。以前用jWebSocket做过一些项目,相对来说,改jWebSocket的源码略复杂,也不是一天两天能搞定的。一调研才发现,现在很多主流的web框架都已经开始支持WebSocket了,不得不感慨时间太快,科技进步太快,在微策略的几年真的荒废了。不多说,先记录下今天的研究。

Tomcat:

J2EE下面用的最多的容器应该就是tomcat了。说到tomcat对WebSocket的支持,不得不先提一下,目前的WebSocket协议已经经过了好几代的演变,不同浏览器对此协议的支持程度也不同,因此,如果作为服务器,最理想的是支持尽可能多的WebSocket协议版本。

tomcat8真正支持jsr-356(包含对websocket的支持), tomcat7支持部分版本的websocket实现不兼容jsr-356。因此,能用tomcat8的话,还是尽量用。

代码实现相当简单,以下是一个列子,只需要tomcat8的基本库,不需要其他依赖。

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;  

@ServerEndpoint("/websocket")
public class WebSocketTest {  

    @OnMessage
    public void onMessage(String message, Session session) throws IOException,
            InterruptedException {
        // Print the client message for testing purposes
        System.out.println("Received: " + message);
        // Send the first message to the client
        session.getBasicRemote().sendText("This is the first server message");
        // Send 3 messages to the client every 5 seconds
        int sentMessages = 0;
        while (sentMessages < 3) {
            Thread.sleep(5000);
            session.getBasicRemote().sendText("This is an intermediate server message. Count: " + sentMessages);
            sentMessages++;
        }
        // Send a final message to the client
        session.getBasicRemote().sendText("This is the last server message");
    }  

    @OnOpen
    public void onOpen() {
        System.out.println("Client connected");
    }  

    @OnClose
    public void onClose() {
        System.out.println("Connection closed");
    }
}  

Jetty:

Jetty和Tomcat一样,也是一个Servlet的容器。如果说不同之处,那么最大的不同应该是Tomcat采用的是BIO处理方式,也就是说一个request会用一个线程去处理,即使是WebSocket这种长连接,也是会独立开一个线程。作为一个普通的Web服务器,tomcat可以轻松应对耗时比较短的Request/Response。但是如果换成是长连接的WebSocket,那麻烦就来了,对于上万用户的聊天和推送,总不能开上万个线程去处理吧。此时,Jetty的性能就体现出来了,Jetty采用的是NIO,一个线程可以处理多个WebSocket的长链接,如果你的需求是大量耗时比较长的request或者大量长连接,那么建议采用Jetty。

Jetty对WebSocket的实现有点绕,Servlet不再是继承原来的HttpServlet,而是继承WebSocketServlet。此处要注意导入jetty-util.jar和jetty-websocket.jar两个包,否则可能会有class not found错误。

ReverseAjaxServlet.java:

import java.io.IOException;
import java.util.Date;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jettison.json.JSONArray;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;

/**
 * @author Mathieu Carbou ([email protected])
 */
public final class ReverseAjaxServlet extends WebSocketServlet {

    private final Endpoints endpoints = new Endpoints();
    private final Random random = new Random();
    private final Thread generator = new Thread("Event generator") {
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(random.nextInt(5000));
                    endpoints.broadcast(new JSONArray().put("At " + new Date()).toString());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    };

    @Override
    public void init() throws ServletException {
        super.init();
        generator.start();
    }

    @Override
    public void destroy() {
        generator.interrupt();
        super.destroy();
    }

    @Override
    public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
        return endpoints.newEndpoint();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("11111");
    }
}

Endpoints.java:

package com.cn.test.chapter2.websocket;

import org.eclipse.jetty.websocket.WebSocket;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @author Mathieu Carbou ([email protected])
 */
final class Endpoints {
    private final Queue<Endpoint> endpoints = new ConcurrentLinkedQueue<Endpoint>();

    void broadcast(String data) {
//        for (Endpoint endpoint : endpoints) {
//            endpoint.onMessage(data);
//        }
    }

    void offer(Endpoint endpoint) {
        endpoints.offer(endpoint);
    }

    void remove(Endpoint endpoint) {
        endpoints.remove(endpoint);
    }

    public WebSocket newEndpoint() {
        return new Endpoint(this);
    }
}

Endpoint.java

import java.io.IOException;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.codehaus.jettison.json.JSONArray;
import org.eclipse.jetty.websocket.WebSocket;

/**
 * @author Mathieu Carbou ([email protected])
 */
class Endpoint implements WebSocket.OnTextMessage  {

    protected Connection _connection;

    private Endpoints endpoints;

    private static int clientCounter = 0;
    private int clientId = clientCounter++;

    public Endpoint(Endpoints endpoints) {
        this.setEndpoints(endpoints);
    }

    @Override
    public void onClose(int code, String message) {
    	System.out.println("Client disconnected");  

        this.endpoints.remove(this);
    }

    @Override
    public void onOpen(Connection connection) {
    	System.out.println("Client connected");
        _connection = connection;
        try {
            this._connection.sendMessage(new JSONArray().put("ClientID = " + clientId).toString());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        endpoints.offer(this);
    }

    @Override
    public void onMessage(final String data) {
    	System.out.println("Received data: " + data);
        this.endpoints.broadcast(data);
    }

    public Endpoints getEndpoints() {
        return endpoints;
    }

    public void setEndpoints(Endpoints endpoints) {
        this.endpoints = endpoints;
    }
}

辅助工具:

在编写服务器最麻烦的是要写对应的客户端来测试,还好Chrome为我们解决了这个问题。下载Chrome插件WebSocket Clinet可以轻松地和服务器建立连接,发送消息到服务器。

时间: 2024-10-11 09:12:41

Tomcat和Jetty对WebSocket的支持的相关文章

Web服务(Apache、Nginx、Tomcat、Jetty)与应用(LAMP)

Web服务和应用是目前信息技术领域的热门技术.如何使用Docker来运行常见的Web服务器(包括Apache.Nginx.Tomcat等),以及一些常用应用(LAMP.CMS等).包括具体的镜像构建方法与使用步骤. 两种创建镜像的过程.其中一些操作比较简单的镜像使用Dockerfile来创建,而像Weblogic这样复杂的应用,则使用commit方式来创建. Apache Apache是一个高稳定性的.商业级别的开源Web服务器.目前Apache已经是世界使用排名第一的Web服务器软件.由于其良

Tomcat学习总结(7)——Tomcat与Jetty比较

Jetty 基本架构 Jetty目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器. 它有一个基本数据模型,这个数据模型就是 Handler(处理器),所有可以被扩展的组件都可以作为一个 Handler,添加到 Server 中,Jetty 就是帮你管理这些 Handler. 下图是 Jetty 的基本架构图,整个 Jetty 的核心组件由 Server 和 Connector 两个组件构成,整个 Server 组件是基于 Handler 容

一.配置简单的嵌入式tomcat和jetty

我们写了一个web应用,打成war包后,就需要找一个server来部署.对于我们的实际应用,我们基本没必要自己再写一个嵌入式的server.接下来两篇文章只是以钻研的心态来学习一下嵌入式tomcat和jetty. 促使我去写这篇文章是因为在我看来,gretty不完美,无论用tomcat还是jetty,修改类之后,reload几次内存占用高涨,硬盘读写频繁,最终感到无奈(应用存在内存不正确释放,或许我使用的方式不对).我选用了<<gradle的war插件>>简单开发的web应用,此例

总结:Apache/Tomcat/JBOSS/Jetty/Nginx区别 .

总结:Apache/Tomcat/JBOSS/Nginx区别 .1.Apache是Web服务器,Tomcat是应用(Java)服务器.Tomcat在中小型系统和并发访问用户不是很多的场合下被普遍使用.Apache支持静态页,Tomcat支持动态的.2.Jetty:Tomcat内核作为其Servlet容器引擎,并加以审核和调优.大中型系统可以应用.能够提供数据库连接池服务,还支持其他 Web 技术的集成,譬如PHP..NET 两大阵营.3.JBoss是一个管理EJB的容器和服务器,但JBoss核心

Eclipse J2EE+Maven+Tomcat(Jetty)构建Spring MVC项目

一步一步的我们试着使用Eclipse J2EE+Maven+Tomcat(Jetty) 搭建留住的web开发平台 Spring MVC的方法. 工具:Eclipse J2EE,Maven,Tomcat Eclipse J2EE+Maven+Tomcat(Jetty):http://www.eclipse.org/downloads/ Maven 3.3.3:http://maven.apache.org/download.cgi Tomcat 7.X:http://tomcat.apache.o

Jetty:配置JSP支持

选择JSP实现 从Jetty-9.2开始,使用Apache Jasper作为默认JSP容器实现.在前面的版本中使用的是Glassfish Jasper,在后面的版本中也可以继续使用它. Jetty发布默认激活jsp模块,默认,模块设置到Apache Jasper.为了改为使用Glassfish Jasper,编辑$JETTY_HOME/start.d/jsp.mod,改变下面的行: # # Jetty JSP Module # [depend] servlet jsp-impl/${jsp-im

IntelliJ IDEA使用(二):tomcat和jetty配置

上一讲用idea创建了maven web项目,接下来我们把项目发布到tomcat和jetty运行,以便进一步地开发和调试 配置tomcat 第一.打开菜单栏 第二.点击设置按钮,添加应用服务器,选择tomcat server 选择tomcat目录 添加后如下所示 到此我们已经把tomcat服务器添加进idea了,接下来还得设置maven web项目的部署信息 第三.设置部署文件 ctrl + shift + alt + s 快捷键打开Project Structure 设置Modules: 检查

MQTT协议笔记之mqtt.io项目Websocket协议支持

前言 MQTT协议专注于网络.资源受限环境,建立之初不曾考虑WEB环境,倒也正常.虽然如此,但不代表它不适合HTML5环境. HTML5 Websocket是建立在TCP基础上的双通道通信,和TCP通信方式很类似,适用于WEB浏览器环境.虽然MQTT基因层面选择了TCP作为通信通道,但我们添加个编解码方式,MQTT Over Websocket也可以的. 这样做的好处,MQTT的使用范畴被扩展到HTML5.桌面端浏览器.移动端WebApp.Hybrid等,多了一些想像空间.这样看来,无论是移动端

Maven tomcat和jetty的配置插件

pom.xml中的插件tomcat或jetty的配置 <plugins> <!--tomcat插件 --> <!-- 启动:tomcat7:run 停止需强制退出,点停止按钮或ctrl+c,使用maven的tomcat7:shutdown并不能关闭. path 和port指明了访问的url端口和地址,若想path指向项目名:则可以使用来${project.build.finalName}来引用项目名 访问主页的路径 :http://localhost:9999/ -->