基于tomcat运行HTML5 WebSocket echo例子

简介: 基于tomcat运行HTML5 WebSocket echo例子

一:概述


作为HTML5新特性之一的WebSocket组件,在实时性有一定要求的WEB应用开发中还是有一定用武之地,高版本的IE、Chrome、FF浏览器都支持Websocket,标准的Websocket通信是基于RFC6455实现服务器端与客户端握手与消息接发的。如果对Websocket通信不是太理解,可以查看RFC文档即可,简单说就是通过发送HTTP请求,实现双方握手,将无状态的HTTP通信协议进一步升级成有状态的通信协议,同时Websocket还支持子协议选项与安全传输。标准的websocket连接URL以ws开头,如果是基于TLS的则以wss开头。基于Websocket可以很方便的开发基于web聊天程序,各种网页消息通知与推送通知。


        如果非要扒一扒websocket的今生前世的话,还记得最早的基于HTTP轮询实现网页即时通信的方式,那种做法比较消耗资源、于是有人改进了编程CometD长连接方式,可是本质上还是换汤不换药,而websocket的出现正好解决了这些问题,但是很多浏览器的低版本还是不支持websocket,于是还催生了一些基于websocket理念实现的JS通信框架,其中学得比较像的有SockJS与socket.io,他们都号称支持websocket,然后如果浏览器端不支持原生的websocket,它们会自动启用fallback选项使用其它诸如ajax、Http轮询、长轮询/连接、甚至是flash的socket等机制实现模拟websocket的工作方式,但是他们最大的弊端是如果客户端使用了这些框架,服务器必须用它们,否则等待开发者就是一大堆无法回避的问题,同时很多都是无解的。主要原因在于它们实现自己的协议集,不照它们的格式处理数据没法玩。闲话说的有点多。


二 : 实现步骤


Tomcat7的高版本中实现了websocket服务器端RFC6455标准协议,可以跟浏览器端websocket进行通信,首先要做好如下几步:


1.      安装高版本JDK – JDK8


2.      安装tomcat 7.0.64


3.      在eclipse中建立一个动态的web项目



根据JSR标准,Java中实现websocket的标准接口可以基于注解方式,tomcat也搞好了,只有我们实现如下代码,即可创建一个websocket回声服务器:

package com.websocket.demo;
 
import java.io.IOException;
import java.nio.ByteBuffer;
 
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
 
@ServerEndpoint(value = "/echo")
public class EchoExample {
  
  @OnMessage
  public void echoTextMessage(Session session, String msg, boolean last) {
    try {
      if (session.isOpen()) {
        System.out.println("received from client message = " + msg);
        session.getBasicRemote().sendText(msg, last);
      }
    } catch (IOException e) {
      try {
        session.close();
      } catch (IOException e1) {
      }
    }
  }
  
  @OnOpen
    public void openConn(Session session) throws IOException {
      session.getBasicRemote().sendText("hello web socket"); // means open it
    }
  
    @OnMessage
    public void echoBinaryMessage(Session session, ByteBuffer bb, boolean last) {
      System.out.println("send binary message...");
        try {
            if (session.isOpen()) {
              System.out.println("byte buffer lenghth : " + bb.array().length);
              System.out.println("byte buffer content: " + ((bb.array()[0]) & 0xff));
              System.out.println("byte buffer content: " + ((bb.array()[1]) & 0xff));
              System.out.println("byte buffer content: " + ((bb.array()[2]) & 0xff));
                session.getBasicRemote().sendBinary(bb, last);
            }
        } catch (IOException e) {
            try {
                session.close();
            } catch (IOException e1) {
                // Ignore
            }
        }
    }
 
}

如何在tomcat中启动websocket服务器,首先需要在web.xml添加如下配置:

  <listener>
    <listener-class>org.apache.tomcat.websocket.server.WsContextListener</listener-class>
  </listener>

然后实现ServerApplicationConfig接口,实现如下:

/*
 *
 */
package com.config.websocket.client;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
 
public class ScanWebSocketSeverConfig implements ServerApplicationConfig {
 
  @Override
  public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> scanned) {
 
    Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();
/*    if (scanned.contains(EchoWsChatSever.class)) {
      result.add(ServerEndpointConfig.Builder.create(EchoWsChatSever.class, "/echo").build());
    }*/
    return result;
  }
 
  @Override
  public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
    Set<Class<?>> results = new HashSet<Class<?>>();
    for (Class<?> clazz : scanned) {
      if (clazz.getPackage().getName().startsWith("com.websocket.")) {
        System.out.println("find end point : " + clazz.getName());
        results.add(clazz);
      }
    }
    return results;
  }
}

创建网页echo.html,内容如下:

<html>
<head>
<title>Web Socket Echo Test</title>
<script>
        var ws = null;
    var count = 0;
        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('echo').disabled  = !connected;
        }
 
        function connect() {
            var target = document.getElementById('target').value;
            if (target == '') {
                alert('Please select server side connection implementation.');
                return;
            }
 
            if ('WebSocket' in window) {
                ws = new WebSocket(target);
            } else if ('MozWebSocket' in window) {
                ws = new MozWebSocket(target);
            } else {
                alert('WebSocket is not supported by this browser.');
                return;
            }
            
            ws.onopen = function () {
                setConnected(true);
                log('Info: WebSocket connection opened.');
            };
            ws.onmessage = function (event) {
                log('Received: ' + event.data);
                if(event.data instanceof ArrayBuffer)
                {
                  var bytes = new Uint8Array(event.data);
                  alert(bytes.length + " : " + bytes[0]);
                }
            };
            ws.onclose = function (event) {
                setConnected(false);
                log('Info: WebSocket connection closed, Code: ' + event.code + (event.reason == "" ? "" : ", Reason: " + event.reason));
            };
            
        }
 
        function disconnect() {
            if (ws != null) {
              ws.doClose();
              ws = null;
            }
            setConnected(false);
        }
 
        function echo() {
            if (ws != null) {
                var message = document.getElementById('message').value;
                log('Sent: ' + message);
                ws.send(JSON.stringify({'textMessage': message})); 
                count++
            } else {
                alert('WebSocket connection not established, please connect.');
            }
        }
 
        function log(message) {
            var echomsg = document.getElementById('echomsg');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message));
            echomsg.appendChild(p);
            while (echomsg.childNodes.length > 25) {
              echomsg.removeChild(console.firstChild);
            }
            echomsg.scrollTop = console.scrollHeight;
        }
 
        document.addEventListener("DOMContentLoaded", function() {
            // Remove elements with "noscript" class - <noscript> is not allowed in XHTML
            var noscripts = document.getElementsByClassName("noscript");
            for (var i = 0; i < noscripts.length; i++) {
                noscripts[i].parentNode.removeChild(noscripts[i]);
            }
        }, false);
</script>
</head>
<body>
  <div>
    <h4>URL - ws://localhost:8080/websocket/echo</h4>
    <input id="target" type="text" size="40" style="width: 350px" />
  </div>
  <div>
    <button id="connect" οnclick="connect();">Connect</button>
    <button id="disconnect" disabled="disabled" οnclick="disconnect();">Disconnect</button>
  </div>
  <div>
    <textarea id="message" style="width: 350px">Here is a message!</textarea>
  </div>
  <div>
    <button id="echo" οnclick="echo();" disabled="disabled">Echo message</button>
  </div>
  <div id="echomsg">
  </div>
</body>
</html>

三 :运行与测试

打包部署到tomcat之后,启动chrom浏览器,输入地址:

http://localhost:8080/websocket/echo.html

后来,我还发现,tomcat实现websocket服务器端居然不支持子协议

跟3W上的测试URL结果不一样。

相关文章
|
1月前
|
网络协议 Java 应用服务中间件
Tomcat中的WebSocket是如何实现的?
【10月更文挑战第7天】本文介绍了WebSocket在Tomcat中的实现,包括其全双工通信、单个TCP连接、协议升级和事件驱动的特点。通过Spring Boot项目整合WebSocket,展示了如何配置依赖、创建WebSocket处理类和配置类。详细解析了WebSocket的原理,包括ServerEndpointExporter的注册过程和请求处理流程。总结了WebSocket与HTTP请求处理的区别,并提供了进一步学习的资源。
Tomcat中的WebSocket是如何实现的?
|
1月前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。
|
1月前
|
移动开发 监控 安全
HTML5 WebSocket详解
**WebSocket** 是一种协议,支持浏览器与服务器间的双向全双工通信。不同于传统的 HTTP 模式,WebSocket 建立持久连接,使服务器能主动向客户端推送数据。本文详细解析 WebSocket 的工作原理、优缺点及应用场景,并提供客户端和服务器端的代码示例。WebSocket 适合实时聊天、在线游戏、数据监控等场景,能显著提升用户体验和应用性能,但需注意其实现复杂性和安全性问题。
|
3月前
|
缓存 Java 应用服务中间件
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
这篇文章详细介绍了在SpringMVC中创建JSP页面的全过程,包括项目的创建、配置、Tomcat的设置,以及如何实现页面跳转和配置模板解析器,最后还对比了JSP和HTML模板解析的差异。
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
|
3月前
|
前端开发
HTML网页作业代码(仿写商城首页、学校官网网页等、源码可直接运行)
这篇文章提供了HTML网页作业的完整代码,包括仿写商城首页和学校官网网页的源码,以及如何运行和项目结构等详细信息。
HTML网页作业代码(仿写商城首页、学校官网网页等、源码可直接运行)
|
3月前
|
缓存 前端开发 Java
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(-Xms512m -Xmx1204m)?
|
4月前
|
弹性计算 运维 应用服务中间件
容器的优势,在Docker中运行Tomcat
摘要:了解Docker与虚拟机的区别:虚拟机使用Hypervisor创建完整操作系统,而容器通过namespace和cgroup实现轻量级隔离,共享主机内核。Docker启动快、资源利用率高,适合快速部署和跨平台移植。但安全性相对较低。示例介绍了如何通过Docker搜索、拉取官方Tomcat镜像并运行容器,最后验证Tomcat服务的正常运行。
|
4月前
|
应用服务中间件
修改Tomcat路径不变怎么办,点击clear清空,重新运行
修改Tomcat路径不变怎么办,点击clear清空,重新运行
|
6月前
|
运维 Java 应用服务中间件
Tomcat详解(六)——Tomcat运行模式调优
Tomcat详解(六)——Tomcat运行模式调优
45 6
|
6月前
|
运维 Java 应用服务中间件
Tomcat详解(六)——Tomcat运行模式调优
Tomcat详解(六)——Tomcat运行模式调优
40 3