WebSocket Java学习与实现
2015-12-20 22:28
387 查看
WebSocket学习与实现
目录
1WebSocket Protocol
2WebSocket 服务端实现
3WebSocket客户端实现
4WebSocket调试
5后记
Websocket协议它的描述如下:
websocket协议允许在客户端和服务端之间建立一条双向传递信息的通道,它是建立在TCP协议之上的,首先通过”握手“来确认和建立通道,之后客户端和服务端可以通过这个通道传递信息,而不需要再次发起请求,而且客户端和服务端都可以主动的发送消息。这种技术不依赖于HTTP连接(比如XMLHttpRequest,iframe),可以实现实时消息传递。
Websocket的建立过程如下:
Created with Raphaël 2.1.0客户端客户端服务端服务端shankehand(握手)对请求消息头进行识别和签名握手确认通道建立成功消息传递消息传递
整个过程大体分为两个阶段:握手和数据传输
客户端向服务端发起的握手消息头如下:
服务端对握手请求成功的回应为:
至此,握手成功,也就是通道已经成功建立,可以进行数据传输。
查看网络连接如下:
Request URL:ws://server.example.com/chat
Request Method:GET
Status Code:101 Switching Protocols
请求协议为ws,方法为GET,成功返回状态为101。消息头中的Sec-WebSocket-Key和Sec-WebSocket-Accept为base-64编码的,且Sec-WebSocket-Key为随机生成的,Sec-WebSocket-Accept则为服务端对Sec-WebSocket-Key进行SHA-1 hash计算后返回的base-64编码的字符串。
接下来,我们通过程序来研究一下Websocket,工具:
JDK 7, Eclipse Kepler, Tomcat 7.0.67, Chrome 47, Window 10
在websocket-api中,我们使用注解来完成服务端的配置可实现,用到的注解有
在写本案例时,新建的是Maven工程,工程名为websocket(此工程已提交到Github,地址见底部),目录结构为:
WebSocketServer的代码为:
为了探究请求,还特意添加一个过滤器,DispatcherFilter.java,代码如下:
同时也别忘了日志的配置信息:
log4j.rootLogger=DEBUG,STDOUT
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Threshold=DEBUG
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern= %d %5p (%c:%L) - %m%n
服务端的实现代码就是这些。
这些代码已经完成WebSocket的建立和消息传输,这些代码位于
http://localhost:8080/websocket/
当然,tomcat的默认端口为8080,如有冲突或其他,可在Server.xml中修改配置。
记得同时打开Google的开发工具F12,待会儿要查看请求头:
查看网络请求状况:
清楚的可以看见请求头和响应头,而此时查看服务器的控制台,则有如下信息:
2015-12-20 22:12:03,913 INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/
2015-12-20 22:12:03,931 INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/chat
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:22) - WebSocket is opening…
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:24) - Sesson id: 6
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:25) - Query string: query=Picasso
从过滤器拦截日志可以看出,websocket的建立显示通过http请求来进行握手,之后则在建立好的通道上传输数据。
如有问题,欢迎指教
参考资料:
http://www.w3.org/TR/websockets/
https://tools.ietf.org/html/rfc6455
http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html
https://jcp.org/en/jsr/detail?id=356
本案例项目地址:https://github.com/FlowerBirds/WebSocketExplorer
首次使用Github,Maven也不是很熟,还请多多包涵。
(不得不说,CSDN的Markdown编辑器真不赖)
目录
1WebSocket Protocol
2WebSocket 服务端实现
3WebSocket客户端实现
4WebSocket调试
5后记
1、WebSocket Protocol
WebSocket协议标准是在2014年8月13日被JCP确认发布,也就是JSR356,具体详情,请点击这里。Websocket协议它的描述如下:
websocket协议允许在客户端和服务端之间建立一条双向传递信息的通道,它是建立在TCP协议之上的,首先通过”握手“来确认和建立通道,之后客户端和服务端可以通过这个通道传递信息,而不需要再次发起请求,而且客户端和服务端都可以主动的发送消息。这种技术不依赖于HTTP连接(比如XMLHttpRequest,iframe),可以实现实时消息传递。
Websocket的建立过程如下:
Created with Raphaël 2.1.0客户端客户端服务端服务端shankehand(握手)对请求消息头进行识别和签名握手确认通道建立成功消息传递消息传递
整个过程大体分为两个阶段:握手和数据传输
客户端向服务端发起的握手消息头如下:
GET /chat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Origin: http://example.com Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13
服务端对握手请求成功的回应为:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= Sec-WebSocket-Protocol: chat
至此,握手成功,也就是通道已经成功建立,可以进行数据传输。
查看网络连接如下:
Request URL:ws://server.example.com/chat
Request Method:GET
Status Code:101 Switching Protocols
请求协议为ws,方法为GET,成功返回状态为101。消息头中的Sec-WebSocket-Key和Sec-WebSocket-Accept为base-64编码的,且Sec-WebSocket-Key为随机生成的,Sec-WebSocket-Accept则为服务端对Sec-WebSocket-Key进行SHA-1 hash计算后返回的base-64编码的字符串。
接下来,我们通过程序来研究一下Websocket,工具:
JDK 7, Eclipse Kepler, Tomcat 7.0.67, Chrome 47, Window 10
2、WebSocket 服务端实现
我们将使用到websocket-api,这个JAR包则在Tomcat的lib下面,新建工程后,需要将Server Library添加到构建路径中(期间我尝试过只引用这个包,而使用低版本的Tomcat,websocket则无法成功),而在同目录下有个tomcat7-websocket包,具体作用未探知。在websocket-api中,我们使用注解来完成服务端的配置可实现,用到的注解有
@ServerEndpoint,
@OnOpen,
@OnMessage,
@OnClose.
在写本案例时,新建的是Maven工程,工程名为websocket(此工程已提交到Github,地址见底部),目录结构为:
WebSocketServer的代码为:
@ServerEndpoint("/chat") public class WebSocketServer { private Session session; private Logger logger = Logger.getLogger(WebSocketServer.class); @OnOpen public void open(Session session){ this.session = session; logger.info("WebSocket is opening..."); logger.info("Sesson id: " + this.session.getId()); logger.info("Query string: " + this.session.getQueryString()); } @OnMessage public void onMessage(String message){ logger.info("Client send message: " + message); try { this.session.getBasicRemote().sendText("Server message form Websocket server"); } catch (IOException e) { e.printStackTrace(); } } @OnClose public void onClose(){ logger.info("Websocket closed"); } }
为了探究请求,还特意添加一个过滤器,DispatcherFilter.java,代码如下:
@WebFilter(urlPatterns={"/*"}) public class DispatcherFilter implements Filter { private Logger logger = Logger.getLogger(DispatcherFilter.class); public void destroy() { // Auto-generated method stub } public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException { // Auto-generated method stub HttpServletRequest request = (HttpServletRequest) arg0; logger.info("Request URL: " + request.getRequestURL()); chain.doFilter(arg0, arg1); } public void init(FilterConfig arg0) throws ServletException { // Auto-generated method stub } }
同时也别忘了日志的配置信息:
log4j.rootLogger=DEBUG,STDOUT
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Threshold=DEBUG
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern= %d %5p (%c:%L) - %m%n
服务端的实现代码就是这些。
3、WebSocket客户端实现
这里所说的客户端就指的是浏览器,在浏览器端的实现则是需要对HTML5的支持,当然,谷歌浏览器为首选,毋庸置疑,他是对这些支持最好的而且调试很方便(顺便鄙视一下某E浏览器)。var webSocket = new WebSocket('ws://localhost:8080/websocket/chat?query=Picasso'); webSocket.onerror = function(event) { //TODO }; webSocket.onopen = function(event) { //TODO }; //接受消息 webSocket.onmessage = function(event) { //TODO console.log(event.data) }; //发送消息 webSocket.send('hello ' + Math.random());
这些代码已经完成WebSocket的建立和消息传输,这些代码位于
src\main\webapp\index.jsp中,其余样式和布局代码,不再这里贴出,请查看源码。
4、WebSocket调试
首先,将此工程添加到Eclipse Servers视图新建的tomcat服务器中,启动。打开浏览器输入地址:http://localhost:8080/websocket/
当然,tomcat的默认端口为8080,如有冲突或其他,可在Server.xml中修改配置。
记得同时打开Google的开发工具F12,待会儿要查看请求头:
查看网络请求状况:
清楚的可以看见请求头和响应头,而此时查看服务器的控制台,则有如下信息:
2015-12-20 22:12:03,913 INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/
2015-12-20 22:12:03,931 INFO (cc.eabour.websocket.filter.DispatcherFilter:30) - Request URL: http://localhost:8080/websocket/chat
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:22) - WebSocket is opening…
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:24) - Sesson id: 6
2015-12-20 22:12:03,933 INFO (cc.eabour.websocket.WebSocketServer:25) - Query string: query=Picasso
从过滤器拦截日志可以看出,websocket的建立显示通过http请求来进行握手,之后则在建立好的通道上传输数据。
5、后记
通过简单的实现来了解一下WebSocket的工作原理和实现方法,后续将进一步强化和增加实现案例。如有问题,欢迎指教
参考资料:
http://www.w3.org/TR/websockets/
https://tools.ietf.org/html/rfc6455
http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html
https://jcp.org/en/jsr/detail?id=356
本案例项目地址:https://github.com/FlowerBirds/WebSocketExplorer
首次使用Github,Maven也不是很熟,还请多多包涵。
(不得不说,CSDN的Markdown编辑器真不赖)
相关文章推荐
- Java进阶篇
- 关于Random,ThreadLocalRandom,SecureRandom的几点思考
- java学习——数组
- java中String的常用方法
- 使用java递归实现文件及文件夹的复制
- java axis2初次接触
- eclipse启动后提示Error when loading the SDK:
- android 开发环境之JDK+eclipse+ADT
- myeclipse关闭项目的作用
- Java开发之多线程下载和断点续传
- SpringMVC的配置详解
- Java基础知识
- JAVA入门第三季
- 移位操作符
- 类访问及java代码编写的限制
- 为MyEclipse指定JDK
- java线程同步——条件对象+synchronized 关键字
- Eclipse 的 Debug 介绍与技巧【转载】
- 深度优先遍历 java
- Java中异常处理和设计