设为首页 收藏本站
查看: 828|回复: 0

[经验分享] 【转】HTML5的WebSocket

[复制链接]

尚未签到

发表于 2017-2-28 09:58:42 | 显示全部楼层 |阅读模式
Introduction:
准备实践一些HTML5的新技术来强化项目的工具。设计后台交互部分选择了HTML5的WebSocket,研究了一下基本的用法,想写点对于WebSocket实践的感受。

个人觉得WebSocket的出现是对于Web应用交互性设计的一次革新。WebSocket提出之前,为了解决后台推送消息到前台的需求,提出了一些解决方案,这些方案使用已有的技术(如ajax,iframe,flashplayer,java applet ...),通过一些变通的处理来实现。基本思路都是通过轮询的方式不断的由Client Browser向Server请求任何数据和页面的变化,亦或通过长连接的方式借助第三方插件来达到即时的收到Server的数据。

而WebSocket允许后台随时向前端发送文本或者二进制消息,WebSocket是一种全新的协议,不属于http无状态协议,协议名为"ws",这意味着一个websocket连接地址会是这样的写法:ws://localhost:8080/webSocketServer。ws不是http,所以传统的web服务器不一定支持,需要服务器与浏览器同时支持, WebSocket才能正常运行,目前的支持还不普遍,需要特别的web服务器和现代的浏览器。一下是浏览器对WebSocket支持情况:
DSC0000.png


接下来看看基于WebSocket设计的Application常见的架构方式:它的特点是可以支持更多并发连接,并且由于它原理上的双向性,客户端的连接可以Net穿透到有防火墙和Proxy的后台Server上。由于WebSocket的通信协议也非HTML,在新的ws通信协议设计中,大大减少的传输消息的Size,去掉了传统HTML Packet许多冗余的信息。瘦身之后的消息也可以大大提高Web应用的响应性能。
DSC0001.jpg


Demonstration:
目前对WebSocket支持的Web Server也逐渐多了起来,笔者在实践的时候选择的是Jetty 8.1.4
在Jetty的lib中包含一个jetty-websocket的JRA包实现了W3C发布的WebSocket接口规范,并且在jetty-util中也包含的基于JSON格式的通信消息转换类。方便开发者快速的开发WebSocket应用。在后台代码中主要部分是:
1. 继承并实现WebSocketServlet中的doWebSocketConnection方法
2. 实现WebSocket接口中的onOpen, onClose, onMessage等方法




[java] view plaincopyprint?

  • public class AutoAdminServlet extends WebSocketServlet{  
  •     //private static final long serialVersionUID = 1874288265454885922L;   
  •     private final Set<AutoAdminSocket> clients;  
  •     static Logger LOG = Logger.getLogger(AutoAdminServlet.class);  
  •       
  •     public AutoAdminServlet(){  
  •         clients = new HashSet<AutoAdminSocket>();  
  •     }  
  •       
  •     @Override  
  •     public WebSocket doWebSocketConnect(HttpServletRequest req, String message) {  
  •         LOG.info("Set up a web socket connection: "+message);  
  •         return new AutoAdminSocket();  
  •     }  
  •       
  •     class AutoAdminSocket implements WebSocket.OnTextMessage{  
  •         WebSocket.Connection connection;  
  •          
  •         @Override  
  •         public void onMessage(String message) {  
  •             /*
  •             Object json = JSON.parse(message);
  •             if(!(json instanceof Map))
  •                 return;
  •             
  •             @SuppressWarnings("unchecked")
  •             Map<String, String> map = (Map<String, String>)json;
  •             //TODO
  •             */  
  •               
  •             sendMessage(this, null, "Thanks, I received: "+message);  
  •         }  
  •   
  •         @Override  
  •         public void onClose(int code, String message) {  
  •             LOG.info("Closed and removed a client socket connection.");  
  •             clients.remove(this);  
  •         }  
  •   
  •         @Override  
  •         public void onOpen(Connection conn) {  
  •             LOG.info("Received a client socket connection.");  
  •             this.connection = conn;  
  •             clients.add(this);  
  •             sendMessage(this, "open", "sample data");  
  •         }  
  •     }  
  •   
  •     void sendMessage(AutoAdminSocket client, String action, String message){  
  •         try{  
  •             if(message == null || message.isEmpty())  
  •                 message = "n/a";  
  •               
  •             if(action != null)  
  •                 message = "action: "+action+", data: "+message;  
  •               
  •             client.connection.sendMessage(message);  
  •         }catch(IOException ex){  
  •             ex.printStackTrace();  
  •         }  
  •     }  
  • }  
public class AutoAdminServlet extends WebSocketServlet{//private static final long serialVersionUID = 1874288265454885922L;private final Set<AutoAdminSocket> clients;static Logger LOG = Logger.getLogger(AutoAdminServlet.class);public AutoAdminServlet(){clients = new HashSet<AutoAdminSocket>();}@Overridepublic WebSocket doWebSocketConnect(HttpServletRequest req, String message) {LOG.info("Set up a web socket connection: "+message);return new AutoAdminSocket();}class AutoAdminSocket implements WebSocket.OnTextMessage{WebSocket.Connection connection;@Overridepublic void onMessage(String message) {/*Object json = JSON.parse(message);if(!(json instanceof Map))return;@SuppressWarnings("unchecked")Map<String, String> map = (Map<String, String>)json;//TODO*/sendMessage(this, null, "Thanks, I received: "+message);}@Overridepublic void onClose(int code, String message) {LOG.info("Closed and removed a client socket connection.");clients.remove(this);}@Overridepublic void onOpen(Connection conn) {LOG.info("Received a client socket connection.");this.connection = conn;clients.add(this);sendMessage(this, "open", "sample data");}}void sendMessage(AutoAdminSocket client, String action, String message){try{if(message == null || message.isEmpty())message = "n/a";if(action != null)message = "action: "+action+", data: "+message;client.connection.sendMessage(message);}catch(IOException ex){ex.printStackTrace();}}}
前台页面代码部分,主要做好以下几点:
1. 在Javascript中判断浏览器是否支持WebSocket,并提供一些友好提示或者备案方案
2. 创建WebSocket这个Javascript对象,并谨慎管理它: 忌讳滥用不断与Server的建立WebSocket,一般一个Browser终端维护一个连接即可,逻辑的多样性可以通过Command模式来丰富
3. 当Browser需要主动与Server通信时,调用WebSocket API中的send方法
4. 当Server主动推送数据到Browser时,在onMessage方法中dispatch多样的business




[javascript] view plaincopyprint?

  • var log = function(s) {   
  •                 if (document.readyState !== "complete") {   
  •                     log.buffer.push(s);   
  •                 } else {   
  •                     document.getElementById("output").innerHTML += (s + "\n");   
  •                 }   
  •             }  
  •               
  •             log.buffer = [];   
  •          
  •             var socket = null;  
  •             function init(){  
  •                 window.WebSocket = window.WebSocket || window.MozWebSocket;  
  •                 if(!window.WebSocket){  
  •                     log("WebSocket not supported by this browser");  
  •                     return;  
  •                 }  
  •                   
  •                 var webSocket = new WebSocket("ws://127.0.0.1:8080/pulsenet/auto");  
  •                 webSocket.onopen = onopen;  
  •                 webSocket.onclose = onclose;  
  •                 webSocket.onmessage = onmessage;  
  •                   
  •                 socket = webSocket;  
  •             }  
  •               
  •             function onopen(){  
  •                 log("Open a web socket.");  
  •             }  
  •               
  •             function onclose(){  
  •                 log("Close a web socket.");  
  •             }  
  •               
  •             function onmessage(evt){  
  •                 var data = evt.data;  
  •                 if(!data)   return;  
  •                   
  •                 log(data);  
  •                   
  •                 data = JSON.parse(data);  
  •                 if(!data)   return;  
  •             }  
  •               
  •             function send(){  
  •                 socket.send("Hello web socket server!");  
  •             }  
var log = function(s) {  if (document.readyState !== "complete") {  log.buffer.push(s);  } else {  document.getElementById("output").innerHTML += (s + "\n");  }  }log.buffer = [];  var socket = null;function init(){window.WebSocket = window.WebSocket || window.MozWebSocket;if(!window.WebSocket){log("WebSocket not supported by this browser");return;}var webSocket = new WebSocket("ws://127.0.0.1:8080/pulsenet/auto");webSocket.onopen = onopen;webSocket.onclose = onclose;webSocket.onmessage = onmessage;socket = webSocket;}function onopen(){log("Open a web socket.");}function onclose(){log("Close a web socket.");}function onmessage(evt){var data = evt.data;if(!data)return;log(data);data = JSON.parse(data);if(!data)return;}function send(){socket.send("Hello web socket server!");}
End
在笔者大概体验了一下WebSocket之后,总结了一些想法:
1. WebSocket的后台代码需要设计健壮而清晰的算法来判断哪些消息是需要推送给哪些客户端,单个或者多个,或者类似广播的全部推送,对客户端的socket connection管理需要考虑线程安全和唯一性等问题。
2. WebCoekt的前台代码需要根据business设计简洁的协议或者命令,还有数据格式,把轮询的责任转移到Server端,而在Browser端只专注做好主动请求的逻辑。在接收Server推送和Client主动请求二者操作到页面共同的部分时,也要谨慎设计页面数据展示的逻辑和同步问题。

Reference:
1. W3C的WebSocket API: http://www.w3.org/TR/2011/WD-websockets-20110419/

文章来源:http://blog.csdn.net/ant_yan/article/details/7704907

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-348265-1-1.html 上篇帖子: 在linux系统下建立artifactory管理maven库 下篇帖子: MyEclipse 8.5的优化,加快打开打开和编辑的速度
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表