Java实现Websocket
Websocket介绍
在一个 WebSocket应用中, 服务器发布一个 WebSocket端点, 客户端使用这个端点的URI来连接服务器。建立连接之后,websocket协议是对称的;客户端和服务器可以在连接打开的任何时间相互发送消息,而且它们可以在任何时间关闭连接。客户端总是只连接到一 个服务器,而服务器可以接受多个客户端的连接。
WebSocket协议有两部分: 握手和数据传输。 客户端使用一个 WebSocket端点的 URI向它发送一个请求,发起握手过程。这个握手过程与现有基于 HTTP的基石出设施是兼容的:web服务器把它解释为一个 HTTP连接升级请求。
WebSocket支持文本消息(编码为 UTF-8 )和二进制消息。 WebSocket中的控制帧是close、 ping和pong(对ping帧的响应)。 ping和 pong帧可能还包含应用数据。websocket端点由采用以下形式的 URI表示:
- ws://host:port/path?query
- wss://host:port/path?query
ws模式表示一个未加密的 WebSocket连接, wss模式表示一个加密的连接。 port是可选的;对于未加密的连接,默认的端口号是80,对于加密连接。默认的端口号是443。 path部分指示服务器中一个端点的位置。 query部分是可选的。现代 web浏览器实理了 WebSocket协议, 并提供一个 Javascript API来连接端点,发送消息,以及为WebSocket事件指定回调方法(如打开连接、接收消息、关闭连接)。
在Java 中创建WebSocket应用
WebSocket Java API包括以下包:
- javax.websocket.server 包含创建和配置服务端点的注解、类和接口。
- javax.websocket包含客户端和服务端点公共的注解、类、和接口。
WebSocket端点是javax.websocket.Endpoint美的实例. WebSocket Java API允许创建两类端点: 可编程端点和注解端点。
可编程端点
通过扩展Endpoint类来创建一个端点:
package com.zhang;
import java.io.IOException;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
public class EchoEndpoint extends Endpoint{
@Override
public void onOpen(Session session, EndpointConfig config) {
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String msg) {
try {
session.getBasicRemote().sendText("echo:" + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}); }
}
在父类Endpoint有三个生命周期方法:onOpen、onClose、和onError,所以只需实现onOpen即可,后面两个默认为空操作。
创建完端点后,还需要把它启动起来,是通过ServerContainer.addEndpoint来启动。
package com.zhang;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpointConfig;
@WebListener
public class EndpointListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent context) {
ServerContainer container = (ServerContainer) context.getServletContext()
.getAttribute(ServerContainer.class.getName());
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(EchoEndpoint.class, "/echo").build();
try {
container.addEndpoint(config);
} catch (DeploymentException e) {
e.printStackTrace();
}
} @Override
public void contextDestroyed(ServletContextEvent arg0) { }
}
上面代码中,ServerContainer是通过context.getServletContext().getAttribute(ServerContainer.class.getName())来获得,这个在容器启动后,放在ServletContext中
注解端点
package com.zhang;
import java.io.IOException;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/echo")
public class EchoEndpoint{
@OnMessage
public void onMessage(Session session,String msg) {
try {
session.getBasicRemote().sendText("echo:" + msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
用注解就比较简洁,不用通过在监听器里添加端点,容器启动后,自动添加端点。
收发二进制消息
服务端接收消息onMessage(String msg),还是发消息session.getBasicRemote().sendText(“echo:”);都是字符串类,如果要收发二进制的内容,只需把参数名改成ByteBuffer或byte[]数组,例如onMessage(Session session,ByteBuffer buffer) {,session.getBasicRemote().sendBinary(ByteBuffer buffer)
维持客户端状态
由于容器会为每一个连接创建一个端点类实例, 所以可以定义并使用实例变量来存储客户端状态信息。另外, session.getUserProperties方法提供了一个可修改的映射来存储用户属性。
使用编码器和解码器
WebSocket Java API使用编码器和解码器为 WebSocket消息和定制 Java类型之间的转换提供支持。编码器取一个 Java对象,生成一种可以作为 WebSocket消息传输的表示;例如编码器通常会生成 JSON、 XML或二进制表示。解码器完成相反的功能,它读取一个WebSocket消息, 并创建一个 Java对象。这种机制可以简化 WebSocket应用, 因为这样可以使业务逻辑与对象的串行化和逆串行化解耦合。
编码器
在端点中实现以下某个接口:
- 对于文本消息实现 Enooder.Text;
- 对于二进制消息实现 Encoder.Binary
以下是把Java编码成JSON字符串
package com.zhang.quick;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import com.alibaba.fastjson.JSONObject;
public class TextEncoder implements Encoder.Text<ChatMessage>{
@Override
public String encode(ChatMessage chat) throws EncodeException {
return JSONObject.toJSONString(chat);
}
...
}
在@ServerEndpoint注解中添加encoders
@ServerEndpoint(value="/chat",encoders={TextEncoder.class,MessageEncoder.class})
public class ChatEndpoint {
可以看到encoders是个Class数组,说明是可以有多个编码器。
解码器
实现以下某个接口
- 对于文本消息实现Decoder.Text。
- 对于二进制消息实现Decoder.Binary。
public class MessageDecoder implements Decoder.Text<ChatMessage>{
@Override
public ChatMessage decode(String json) throws DecodeException {
return JSON.parseObject(json, ChatMessage.class);
}
...
}
接下来,为@ServerEndpoint注解增加decoder参数
在@ServerEndpoint注解中添加encoders
@ServerEndpoint(value="/chat",encoders={TextEncoder.class,MessageEncoder.class}
,decoders={MessageDecoder.class})
public class ChatEndpoint {
WebSocket JavaScript编程方式
var webSocket = new WebSocket(
'ws://localhost:8080/websocket/echo');
webSocket.onerror = function(event) {
onError(event)
};
webSocket.onopen = function(event) {
onOpen(event)
};
webSocket.onmessage = function(event) {
onMessage(event)
};
function onMessage(event) {
document.getElementById('messages').innerHTML += '<br />'
+ event.data;
}
function onOpen(event) {
document.getElementById('messages').innerHTML = 'Connection established';
}
function onError(event) {
alert(event.data);
}
function start() {
webSocket.send('hello');
return false;
}
代码中var webSocket = new WebSocket(‘ws://localhost:8080/websocket/echo’);里只是创建一个WebSocket对象,没有真正连接到服务器,只有当调用WebSocket.send时才开始连接。
参考资料
- 《Java EE 7权威指南》
Java实现Websocket的更多相关文章
- Java和WebSocket开发网页聊天室
小编心语:咳咳咳,今天又是聊天室,到现在为止小编已经分享了不下两个了,这一次跟之前的又不大相同,这一次是网页聊天室,具体怎么着,还请各位看官往下看~ Java和WebSocket开发网页聊天室 一.项 ...
- Java用WebSocket + tail命令实现Web实时日志
原文:http://blog.csdn.net/xiao__gui/article/details/50041673 在Linux操作系统中,经常需要查看日志文件的实时输出内容,通常会使用tail - ...
- 基于Java的WebSocket推送
WebSocket的主动推送 关于消息推送,现在的解决方案如轮询.长连接或者短连接,当然还有其他的一些技术框架,有的是客户端直接去服务端拿数据. 其实推送推送主要讲的是一个推的概念,WebSocket ...
- java 实现websocket
最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...
- java 实现websocket的三种方式
Java中实现websocket常见有以下三种方式: 使用tomcat的websocket实现,需要tomcat 7.x,JEE7的支持. 使用spring的websocket,spring与webs ...
- java集成WebSocket向指定用户发送消息
一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通 ...
- Java后端WebSocket的Tomcat实现(转载)
一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通 ...
- js使用WebSocket,java使用WebSocket
js使用WebSocket,java使用WebSocket 创建java服务端代码 import java.net.InetSocketAddress; import org.java_websock ...
- Java实现WebSocket服务
一.使用Tomcat提供的WebSocket库 Java可以使用Tomcat提供的WebSocket库接口实现WebSocket服务,代码编写也非常的简单.现在的H5联网游戏基本上都是使用WebSo ...
- Java Springboot webSocket简单实现,调接口推送消息到客户端socket
Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...
随机推荐
- PostgreSQL的streaming replication
磨砺技术珠矶,践行数据之道,追求卓越价值回到上一级页面: PostgreSQL集群方案相关索引页 回到顶级页面:PostgreSQL索引页[作者 高健@博客园 luckyjackgao@gm ...
- Mybaits: MyBaits的xml文件中大于号和小于号的转义
< 小于号 < > 大于号 & & 和 & ' 单引号 ' " 双引号 "
- STM32L431驱动带UC1698芯片调试记录
1, 数据线连接方式,这次使用的是8080格式的接口,如下 2. 主要是信号和数据引脚 DATA0-DATA7 并口的数据 RST 复位信号 WR 写信号 RD 读信号 C/D 数据还是命令 CS片 ...
- JS基础,课堂作业,三个数字排序
三个数字大小排序 <script> var a = parseInt(prompt("请输入第一个整数:")); var b = parseInt(prompt(&qu ...
- KEIL5的安装
安装注意事项 1.最好不要安装在带有中文路径的文件夹. 2.试用版的Keil MDK只能编译32K以下的代码,代码大于32K只能使用正版或破解版才能编译通过. 安装MKD 这里选择MKD512A版本安 ...
- Nginx之一:Nginx的编译安装
一.Nginx简介 官方网址:http://nginx.org/ Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发工作最早从2002年开始, ...
- lxd&openstack-lxd源码剖析
lxd:https://linuxcontainers.org/lxd/,目标是融入到openstack体系被管理,像虚拟机一样被管理使用.从如下图可知,并非走的是libvirt-lxc路线,而是no ...
- IC设计前后端流程与EDA工具
IC前端设计(逻辑设计)和后端设计(物理设计)的区分: 以设计是否与工艺有关来区分二者:从设计程度上来讲,前端设计的结果就是得到了芯片的门级网表电路. 前端设计的流程及使用的EDA工具 1.架构的设计 ...
- 食物链 POJ 1182(种类并查集)
Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到 ...
- Scrum立会报告+燃尽图(十月二十五日总第十六次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...