1、WebSocket Protocol
WebSocket协议标准是在2014年8月13日被JCP确认发布,也就是JSR356,具体详情,请点击这里。
Websocket协议它的描述如下:
websocket协议允许在客户端和服务端之间建立一条双向传递信息的通道,它是建立在TCP协议之上的,首先通过”握手“来确认和建立通道,之后客户端和服务端可以通过这个通道传递信息,而不需要再次发起请求,而且客户端和服务端都可以主动的发送消息。这种技术不依赖于HTTP连接(比如XMLHttpRequest,iframe),可以实现实时消息传递。
Websocket的建立过程如下:
整个过程大体分为两个阶段:握手和数据传输
客户端向服务端发起的握手消息头如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
服务端对握手请求成功的回应为:
- 1
- 2
- 3
- 4
- 5
- 6
至此,握手成功,也就是通道已经成功建立,可以进行数据传输。
查看网络连接如下:
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的代码为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
为了探究请求,还特意添加一个过滤器,DispatcherFilter.java,代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
同时也别忘了日志的配置信息:
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浏览器)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这些代码已经完成WebSocket的建立和消息传输,这些代码位于src\main\webapp\index.jsp
中,其余样式和布局代码,不再这里贴出,请查看源码。
4、WebSocket调试
首先,将此工程添加到Eclipse Servers视图新建的tomcat服务器中,启动。打开浏览器输入地址:
当然,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也不是很熟,还请多多包涵。
(不得不说,优快云的Markdown编辑器真不赖)