Java WebSocket 基础知识点及简单实现
2016-09-03 15:26
239 查看
一 、 WebSocket简单介绍
随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。在WebSocket规范提出之前,开发人员若要实现这些实时性较强的功能,经常会使用折衷的解决方法:轮询(polling)和Comet技术。其实后者本质上也是一种轮询,只不过有所改进。
轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。
Comet技术又可以分为长轮询和流技术。长轮询改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。流技术通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。
这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。
伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。
JavaEE 7中出了JSR-356:Java API for WebSocket规范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat从7.0.27开始支持 WebSocket,从7.0.47开始支持JSR-356,所以需要部署在Tomcat7.0.47以上的版本才能运行。
二 、webSocket 实用基础知识点
WebSocket端点的4个生命周期事件
打开事件此事件发生在端点上建立新连接时并且在任何其他事件之前
消息事件
此事件接收WebSocket对话的另外一端发送的消息。它可以发生在WebSocket端点接收了打开事件后并且在接收关闭事件关闭连接之前的任意时刻
错误事件
此事件在WebSocket连接或者端点发生错误时产生
关闭事件
此事件表示WebSocket端点的连接目前正在部分的关闭,它可以由参与连接的任意一个端点发出
注解式端点事件处理
将Java类声明成WebSocket端点,在服务器端端点用@ServerEndpoint来注解,在客户端可以使用@ClientEndpoint来注解。对于端点的四个生命周期事件:打开事件@OnOpen
@OnOpen public void init(Session session,EndpointConfig config){ /* *方法名任意,参数两个任选,可要可不要,其他事件也一样 **/ }
消息事件@OnMessage
@OnMessage public void message(String textMessage,Session session){ //处理文本信息,Session参数可选 } @OnMessage public void message(byte[] messageData,Session session){ //处理二进制信息,Session参数可选 } @OnMessage public void message(String textMessage,boolean isLast){ //处理分片段的文本信息,isLast 为false表示信息没有接收完整,true则表示最后一条信息 } //所有的@OnMessage 也可以有返回值相当于发送消息的功能 @OnMessage public String message(String textMessage,Session session){ //处理文本信息,Session参数可选 return "I got it"; }
错误事件@OnError
@OnError public void errorHandler(Throwable t){ //log error here }
关闭事件@OnClose
@OnClose public void goodbye(){ // }
发送信息
javax.websocket.SessionSession 代表了单客户端的状态,每个客户端与服务端建立连接都会生成唯一的session 属性中有主键id 通过id可以分辨用户
发送字符串消息
RemoteEndpoint.Basic发送文本信息:public void sendText(String text) throws IOEcxeption
RemoteEndpoint.Basic发送文本信息到流:public Writer getSendStream() throws IOEcxeption
RemoteEndpoint以片段形式发送文本消息:public void sendText(String partialMessage,boolean isLast) throws IOException
以小片段序列的形式发送大的字符串消息,调用时isLast参数一般设为false,直到最后一个片段才设为true,表明消息发送完毕。
发送二进制消息
对于大多数应用,发送文本形式消息已经足够,对于有特殊格式例如小图像文件,以二进制形式发送消息则更合适
RemoteEndpoint发送二进制消息:
public void sendBinary(ByteBuffer data) throws IOException
public void sendBinary(ByteBuffer partialByte,boolean isLast) throws IOException 以分片的形式发送,调用时isLast参数一般设为false,直到最后一个片段才设为true,表明消息发送完毕。
RemoteEndpoint.Basic使用流发送二进制消息:
public OutputStream getSendStream() throws IOException
javax.websocket.EndpointConfig: 与多客户端共享的端点状态相关联。
了解以上服务端的基础知识可以处理从客户端接收到的请求和给客户端发送信息。但是如何与客户端建立连接呢?
构建服务端类
@ServerEndpoint("/echo") public class Test { @OnOpen public void name(Session session) { System.out.println("连接成功"); } @OnMessage public void message(String textMessage,Session session{ //处理文本信息,Session参数可选 } ... }
以javascript脚本为客户端讲解:
建立连接定义uri : var wsUri = “ws://localhost:9080/context/echo”;
var ws = new WebSocket(wsUri);
说明:/context 是项目的上下文;/echo 断点的路径 (整个项目中唯一的)
发送消息
ws.onopen = function(){ //成功建立连接之后调用的方法 } //想服务端发送消息 ws.send("文本消息"); websocket.onclose = function() { //关闭建立连接之后调用的方法 }; websocket.onmessage = function(evt) { //服务器返回消息触发的方法 }; websocket.onerror = function(evt) { //产生已成触发的方法 }; //关闭连接 ws.close();
相关文章推荐
- 网络基础知识、在Java中实现UDP协议编程
- Java 基础小知识一: 使用ResourceBundle 和 MessageFormat 实现国际化信息输出
- java基础:Web服务器原理 以及 用java简单实现
- Java基础知识强化91:DateFormat类之DateFormat实现日期和字符串的相互转换
- 一些简单的java基础知识复习。
- android-基础知识:实现简单的拨打电话功能_intent_study
- 黑马程序员--java实现约瑟夫环问题--java学习日记1(基础知识)
- Java基础知识强化05:不借助第三个变量实现两个变量互换
- java零基础知识回顾(io简单总结)
- java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
- 黑马程序员——Java基础语法:几种简单的排序算法的实现
- 【java基础】IOC介绍及其简单实现
- Java基础知识整理(五)- 线程同步的实现方式
- Java核心技术卷I:基础知识(原书第8版):12.2 简单泛型类的定义
- [零基础学JAVA]Java SE应用部分-31.Java IO操作(05)IO操作实例讲解之实现简单MIS 推荐
- 【Java学习笔记】基础知识学习12【Set接口的实现类】
- java基础实现简单的用户登陆功能
- 黑马程序员_java基础知识(5)枚举的简单理解
- Java基础知识强化18:抽象类、接口的区别 和 抽象类可以不实现接口的全部方法
- Java 中UDP原理机制及实现方式介绍(建议阅读者阅读前了解下Java的基础知识,一方便理解)