简单轮询
这是最先的一种实现实时 Web 应用的方案。客户端以必定的时间间隔向服务端发出请求,以频繁请求的方式来保持客户端和服务器端的同步。这种同步方案的最大问题是,当客户端以固定频率向服务器发起请求的时候,服务器端的数据可能并无更新,这样会带来不少无谓的网络传输,因此这是一种很是低效的实时方案。javascript
长轮询
长轮询是对定时轮询的改进和提升,目地是为了下降无效的网络传输。当服务器端没有数据更新的时候,链接会保持一段时间周期直到数据或状态改变或者时间过时,经过这种机制来减小无效的客户端和服务器间的交互。固然,若是服务端的数据变动很是频繁的话,这种机制和定时轮询比较起来没有本质上的性能的提升。java
流:
流技术方案一般就是在客户端的页面使用一个隐藏的窗口向服务端发出一个长链接的请求。服务器端接到这个请求后做出回应并不断更新链接状态以保证客户端和服务器端的链接不过时。经过这种机制能够将服务器端的信息源源不断地推向客户端。这种机制在用户体验上有一点问题,须要针对不一样的浏览器设计不一样的方案来改进用户体验,同时这种机制在并发比较大的状况下,对服务器端的资源是一个极大的考验。web
综合这几种方案,您会发现这些目前咱们所使用的所谓的实时技术并非真正的实时技术,它们只是在用 Ajax 方式来模拟实时的效果,在每次客户端和服务器端交互的时候都是一次 HTTP 的请求和应答的过程,而每一次的 HTTP 请求和应答都带有完整的 HTTP 头信息,这就增长了每次传输的数据量,并且这些方案中客户端和服务器端的编程实现都比较复杂,在实际的应用中,为了模拟比较真实的实时效果,开发人员每每须要构造两个 HTTP 链接来模拟客户端和服务器之间的双向通信,一个链接用来处理客户端到服务器端的数据传输,一个链接用来处理服务器端到客户端的数据传输,这不可避免地增长了编程实现的复杂度,也增长了服务器端的负载,制约了应用系统的扩展性。spring
WebSocket 设计出来的目的就是要取代轮询和 Comet 技术,使客户端浏览器具有像 C/S 架构下桌面系统的实时通信能力。 浏览器经过 JavaScript 向服务器发出创建 WebSocket 链接的请求,链接创建之后,客户端和服务器端就能够经过 TCP 链接直接交换数据。由于 WebSocket 链接本质上就是一个 TCP 链接,因此在数据传输的稳定性和数据传输量的大小方面,和轮询以及 Comet 技术比较,具备很大的性能优点。Websocket.org 网站对传统的轮询方式和 WebSocket 调用方式做了一个详细的测试和比较,将一个简单的 Web 应用分别用轮询方式和 WebSocket 方式来实现,在这里引用一下他们的测试结果图:chrome
经过这张图能够清楚的看出,在流量和负载增大的状况下,WebSocket 方案相比传统的 Ajax 轮询方案有极大的性能优点。这也是为何咱们认为 WebSocket 是将来实时 Web 应用的首选方案的缘由。编程
Spring - 4.0.1
Tomcat - 7.0.52
Web browser - chrome 和 firefox浏览器
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>4.0.1.RELEASE</version> </dependency>
public class WebsocketEndPoint extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session,TextMessage message) throws Exception { super.handleTextMessage(session, message); TextMessage returnMessage = new TextMessage(message.getPayload()+" received at server"); session.sendMessage(returnMessage); } }
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{ @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { System.out.println("Before Handshake"); return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { System.out.println("After Handshake"); super.afterHandshake(request, response, wsHandler, ex); } }
@Configuration @EnableWebSocket public class WebsocketConfig implements WebSocketConfigurer{ @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myhandler(), "/websocket") .addInterceptors(myInterceptors()); } @Bean public WebSocketHandler myhandler() { return new WebsocketEndPoint(); } @Bean public HandshakeInterceptor myInterceptors() { return new HandshakeInterceptor(); } }
2)配置xml服务器
<bean id="websocket" class="***.***.***.WebsocketEndPoint"/> <websocket:handlers> <websocket:mapping path="/websocket" handler="websocket"/> <websocket:handshake-interceptors> <bean class="***.***.***.HandshakeInterceptor"/> </websocket:handshake-interceptors> </websocket:handlers>
到这里,服务端的代码以及配置已经弄好websocket
<script type="text/javascript"> function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; document.getElementById('response').innerHTML = ''; } function connect() { if ('WebSocket' in window){ console.log('Websocket supported'); socket = new WebSocket('ws://localhost:8080//websocket'); console.log('Connection attempted'); socket.onopen = function(){ console.log('Connection open!'); setConnected(true); } socket.onclose = function(){ console.log('Disconnecting connection'); } socket.onmessage = function (evt) { var received_msg = evt.data; console.log(received_msg); console.log('message received!'); showMessage(received_msg); } } else { console.log('Websocket not supported'); } } function disconnect() { setConnected(false); console.log("Disconnected"); } function sendName() { var message = document.getElementById('message').value; socket.send(JSON.stringify({ 'message': message })); } function showMessage(message) { var response = document.getElementById('response'); var p = document.createElement('p'); p.style.wordWrap = 'break-word'; p.appendChild(document.createTextNode(message)); response.appendChild(p); } /* 1. new WebSocket('ws://localhost:8080//websocket')尝试与服务器创建链接; 2. 握手成功并创建链接后,socket.onopen被调用 3. 当接收来自服务器的消息,socket.onmessage被调用 4. socket.send()用来发送消息至服务端 */ </script>
完。网络