websocket技术分享

来源:互联网 发布:windows loader怎么用 编辑:程序博客网 时间:2024/06/10 21:53

websocket进阶

开发环境

spring3+tomcat7+spring-websocket4 + spring security3

运行环境

windows、Linux

 

一、背景:

产品将要发布的消息或其他需要让客户提前知道的消息,在客户端和服务端建立连接后推送

给客户端。

 

二、WebSocket是什么

WebSocket协议是基于TCP的一种新的网络协议。

 

三、WebSocket身世挖掘

1、WebSocket是HTML5出的东西(协议),跟HTTP协议基本没有关系,只是为了兼容现有浏览器的握手规范而已

 

2、HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个

 

3、Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说

 

4、典型的Websocket握手

Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
Origin: http://example.com
 
5、实现了websocket的浏览器
 
ChromeSupported in version 4+ Firefox Supported in version 4+ Opera Supported in version 10+ Safari Supported in version 5+ IE(Internet Explorer) Supported in version 10+

 

 

 

 

 

 

 

 

四、WebSocket的特点

1、长连接,实现双向通信, 具有底层socket的特点,实现真正意义上的推送功能。

2、是HTML5的技术之一,具有巨大的应用前景

3、节约带宽,节省服务器资源

缺点:

少部分浏览器不支持,浏览器支持的程度与方式有区别

 

五、WebSocket如何用

前端代码:

复制代码
 1 var DJCW_webSocket = (function(){ 2     var webSocket = null, 3         tryTime = 0, 4         initSocket; 5      6     initSocket = function(){ 7         debugger 8         var _marquee = "<marquee behavior='scroll' direction='left' behavior='scroll'>"; 9         10         if (!window.WebSocket) {11             alert("您的浏览器不支持websocket!");12             return false;13         }14 15         webSocket = new WebSocket('ws://127.0.0.1:8082/projectname/websocket');16 17         // 收到服务端消息18         webSocket.onmessage = function(msg) {19             DJCW.messagesScroll(msg.data);20         };21 22         // 异常23         webSocket.onerror = function(event) {};24 25         // 建立连接26         webSocket.onopen = function(event) {};27 28         // 断线重连29         webSocket.onclose = function() {30             // 重试10次,每次之间间隔10秒31             if (tryTime < 10) {32                 setTimeout(function() {33                     webSocket = null;34                     tryTime++;35                     initSocket();36                 }, 500);37             } else {38                 tryTime = 0;39             }40         };41     };42     43     initModule =  function() {44         initSocket();45     };    46     return {47         initSocket:initSocket,48         initModule : initModule49     };50 })();51 52 $(function() {53     DJCW_webSocket.initModule();54     window.onbeforeunload = function() {55         // 离开页面时的其他操作56     };57 });
复制代码

 

 后端代码:

复制代码
  1 import java.io.IOException;  2 import java.util.concurrent.CopyOnWriteArraySet;  3   4 import javax.websocket.OnClose;  5 import javax.websocket.OnError;  6 import javax.websocket.OnMessage;  7 import javax.websocket.OnOpen;  8 import javax.websocket.Session;  9 import javax.websocket.server.ServerEndpoint; 10  11  12 import org.springframework.stereotype.Service; 13  14 /** 15  * 功能说明:websocket处理类, 使用J2EE7的标准 切忌直接在该连接处理类中加入业务处理代码 作者:ydd(2017-04-12 15:29) 16  */ 17 // relationId和userCode是我的业务标识参数,websocket是连接的路径,可以自行定义 18 @ServerEndpoint("/websocket") 19 @Service 20 public class WebsocketEndPoint { 21  22     private static final Log LOG = Log.getLogger(WebsocketEndPoint.class); 23  24     private static CopyOnWriteArraySet<WebsocketEndPoint> sessions = new CopyOnWriteArraySet<WebsocketEndPoint>(); 25     private Session session; 26  27  28     public WebsocketEndPoint() { 29     } 30  31     /** 32      * @Title: onOpen  33      * @Description: (打开连接时触发)  34      * @param @param session    设定文件  35      * @return void    返回类型  36      * @throws 37      */ 38     @OnOpen 39     public void onOpen(Session session) { 40         this.session = session; 41         sessions.add(this); 42     } 43  44  45     /**  46      * @Title: onMessage  47      * @Description: (收到客户端消息时触发)  48      * @param @param message 49      * @param @return    设定文件  50      * @return String    返回类型  51      * @throws  52      */ 53     @OnMessage 54     public String onMessage(String message) { 55         return "Got your message (" + message + ").Thanks !"; 56     } 57  58     /**  59      * @Title: onError  60      * @Description: (异常时触发)  61      * @param @param throwable 62      * @param @param session    设定文件  63      * @return void    返回类型  64      * @throws  65      */ 66     @OnError 67     public void onError(Throwable throwable, Session session) { 68         LOG.e("Chat Error: " + throwable.toString()); 69     } 70  71     /**  72      * @Title: onClose  73      * @Description: (关闭连接时触发)  74      * @param @param session    设定文件  75      * @return void    返回类型  76      * @throws  77      */ 78     @OnClose 79     public void onClose(Session session) { 80         sessions.remove(this); 81     } 82  83     /** 84      * 向所有用户发送消息 85      *  86      * @param msg 87      */ 88     public void sendUser(String msg) { 89         try { 90             if (sessions.size() != 0) { 91                 for (WebsocketEndPoint s : sessions) { 92                     if (s != null) { 93                         s.session.getBasicRemote().sendText(msg); 94                     } 95                 } 96             } 97         } catch (IOException e) { 98             e.printStackTrace(); 99         }100     }101     102 }
复制代码

 

六、WebSocket应用场景

在线聊天室、在线客服系统、评论系统、WebIM等

 

七、WebSocket的实现原理

在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” (handshaking)。

 

在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数
据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:
1. Header
互相沟通的Header是很小的-大概只有 2 Bytes
2. Server Push
服务器的推送,服务器不再被动的接收到浏览器的request之后才返回数据,而是在有新数据时就主动推送给浏览器。
 

WebSocket和传统的HTTP交互方式的区别如下图:

 

八、遇到的错误

1、The WebSocket session [5] has been closed and no method
 
2、Message will not be sent because the WebSocket session has been closed
服务端不正常关闭后,在后台的OnError的方法中抛出的异常,可以不抛出异常
 
3、spring security3与WebSocket结合使用时报302循环重定向错误
原因
springsecurity的过滤器DelegatingFilterProxy和springMVC的过滤器DispatcherServlet
冲突所导致的。
解决方案(只将spring security的url-pattern中的/*改为具体的对指定的相关请求进行拦截就可以了)
复制代码
 1     <!-- spring security --> 2     <filter> 3         <filter-name>springSecurityFilterChain</filter-name> 4         <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 5     </filter> 6     <!-- 由于加入了websocket,不能写成/*,不然会出现302循环重定向,因为和 DispatcherServlet相冲突--> 7     <filter-mapping>   8         <filter-name>springSecurityFilterChain</filter-name>   9         <url-pattern>*.js</url-pattern>  10         <url-pattern>*.jsp</url-pattern>11         <!--通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()可以获取到用户名  -->12         <url-pattern>/login/</url-pattern>13         <!-- 登录时springsecurity自带的类进行用户密码认证以及赋予相关权限 -->  14         <url-pattern>/j_spring_security_check</url-pattern>15         <!-- 退出时通过springsecurity自带的url进行退出并清除session -->   16         <url-pattern>/j_spring_security_logout</url-pattern>  17     </filter-mapping> 
复制代码
1 0
原创粉丝点击