• H5新特性websocket


    websocket也是html5的新增加内容之一,号称是下一代客户端/服务器异步通信办法,私以为虽然有点吹牛的成分,但是以后说不定能成为异步通信的半壁江山,至于取代ajax,我觉的应该不会。

    websocket的一个很有意思的特点就是双向通信,这一点其实也不稀奇,跟socket一样的。

    下边是websocket的原理性知识总结是写给我自己看的,如果你没兴趣,可以跳过直接到代码:

    tcp建立连接tcp连接的建立需要经历”三次握手“的过程。过程如下client发送SYN包(值为j)以及SEQ包到server端,此时client进入SYN_SEND状态。此为第一次握手。server端收到SYN包后,发送一个ACK(值为seq+1)确认包和SYN(值为k)给client,此时server进入SYN_RECV状态。此为第二次握手。client收到SYN+ACK包后,向server发送一个ACK(值为k+1),该包发送完成后,client和server均进入ESTABLISH状态。此为第三次握手。

    client和server两端状态变化如下:

    client:

    CLOSED->SYN_SEND->ESTABLISH

    server:

    CLOSED->LISTEN->SYN_RECV->ESTABLISH

    tcp是传输层的协议,tcp三次握手后,应用层协议http也便建立了连接。而对于当今web的发展情况,http仍有许多瓶颈。

    一条连接只能发送一个请求。
    请求只能从客户端开始。客户端不可以接收除响应以外的指令。
    请求/响应首部未经压缩发送,首部信息越多延迟越大。
    发送冗长的首部。每次互相发送相同的首部造成较多的浪费。
    可任意选择数据压缩格式。非强制压缩发送。
    虽然已经出现了很多解决方案,如ajax、comet,但是他们最终使用的都是http协议,因此也无法从根本上解决这些瓶颈。

    因此也就诞生了一个新的通信协议,WebSocket协议,一种全双工通信协议

    该通信协议建立在http协议的基础之上,因此连接的发起方仍然是客户端,在http连接建立之后,再将协议升级为webSocket连接,在webSocket连接建立之后,客户度和服务器端都可以主动向对方发送报文信息了。

    建立webSocket连接,需要先建立http连接,并在此基础上再进行一次”握手“。

    client会发起一个”握手“的请求,请求首部含有upgrade:websocket(还有其他首部,具体看如下示例)。服务器端返回一个101状态码,确认转换协议。完成握手后便可以使用websocket协议进行通信。

    Client(request)

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: AQIDBAUGBwgJCgsMDQ4PEC==
    Origin: http://example.com
    Sec-WebSocket-protocol: chat, superchat
    Sec-WebSocket-Version: 13

    server (response)

    HTTP/1.1 101 switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: dGhlIHNhbXBsZSBub25jZQ==
    Sec-WebSocket-Protocol: chat

    websocket这个协议涉及前端显示,以及服务器处理,我这里使用基础的java+js来实现一个简单的群聊

     1 package example;
     2 
     3 import java.io.IOException;
     4 import java.util.Set;
     5 import java.util.concurrent.CopyOnWriteArraySet;
     6 
     7 import javax.websocket.OnClose;
     8 import javax.websocket.OnError;
     9 import javax.websocket.OnMessage;
    10 import javax.websocket.OnOpen;
    11 import javax.websocket.Session;
    12 import javax.websocket.server.PathParam;
    13 import javax.websocket.server.ServerEndpoint;
    14 
    15 
    16 @ServerEndpoint(value="/ws/chat/{nickName}")
    17 public class Chat {
    18     private static final Set<Chat> connections = new CopyOnWriteArraySet<Chat>();
    19     private String nickName; //接收用户名称
    20     private Session session; //建立的会话
    21     
    22     
    23     public Chat(){
    24         
    25     }
    26     
    27     /*
    28      * 打开连接
    29      */    
    30     @OnOpen
    31     public void onOpen(Session session,@PathParam(value="nickName") String nickName){
    32         this.session=session;
    33         this.nickName=nickName;
    34         connections.add(this);
    35         System.out.println("新用户连接进入,名字是:"+this.nickName);
    36         String message=String.format("System>%s %s",this.nickName,"hasjoined.");
    37         Chat.broadCast(message);
    38         
    39     }
    40     /*
    41      * 关闭连接
    42      */
    43     @OnClose
    44     public void onClose(){
    45         connections.remove(this);
    46         String message=String.format("System> %s, %s", this.nickName,
    47                 " has disconnection.");
    48         Chat.broadCast(message);
    49     }
    50     
    51     /*
    52      * 接收信息
    53      */
    54     @OnMessage
    55     public void onMessage(String message,@PathParam(value="nickName")String nickName){
    56         System.out.println("新消息from:"+nickName+" : "+message);
    57         Chat.broadCast(nickName+">"+message);
    58     }
    59     /*
    60      * 错误消息
    61      */
    62     @OnError
    63     public void onError(Throwable throwable){
    64         System.out.println(throwable.getMessage());
    65     }
    66     /*
    67      * 广播消息
    68      */
    69     private static void broadCast(String message){
    70         for(Chat chat:connections){
    71             try{
    72                 synchronized (chat) { //线程同步控制并发访问
    73                     chat.session.getBasicRemote().sendText(message);
    74                 }
    75             }catch(IOException e){
    76                 connections.remove(chat);
    77                 try{
    78                     chat.session.close();
    79                     
    80                 }catch(IOException e1){
    81                     chat.broadCast(String.format("System> %s %s", chat.nickName,
    82                             " has bean disconnection."));
    83                 }
    84             }
    85         }
    86     }
    87 }
    
    
     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <meta charset="utf-8"/>
     5 <title>Testing websockets</title>
     6 </head>
     7 <body>
     8   <div>
     9       <input type="text" id="yourName"/>
    10     <button id="start">click to start</button>
    11   </div>
    12   <div style="100%;">
    13       <div id="messages" style="border:5px solid red;50%;height:300px;margin-top:20px;"></div>
    14   </div>
    15   <div style="100%;margin-top:20px;">
    16       <div id="sends" style="float:left;50%;height:50px;margin-right:20px;">
    17           <input type="text"  id="MessageUN" style="100%;height:48px;"/>
    18       </div>
    19       <button style="float:left;10%;height:50px;" id="sendMessage">发送</button>
    20   </div>
    21   
    22   <script type="text/javascript">
    23   var button=document.getElementById("start");
    24   button.onclick=function(){
    25       
    26       
    27       
    28       
    29       var name=document.getElementById("yourName");
    30       console.log(name.value);
    31       var websocketAdd="ws://localhost:8080/t8j8/ws/chat/"+name.value;
    32       var webSocket=new WebSocket(websocketAdd); 
    33 
    34       
    35       function onMessage(event) {
    36             document.getElementById('messages').innerHTML 
    37               += '<br />' + event.data;
    38       }
    39 
    40       function onOpen(event) {
    41             document.getElementById('messages').innerHTML 
    42               = 'Connection established';
    43           //一旦链接开始,尝试发出一条通讯消息
    44              start();
    45           alert("消息通道开启,可以发送消息了");
    46           //确认链接开始,就可以开始消息的发送了
    47           //首先绑定一个点击事件
    48           var sendMessage=document.getElementById("sendMessage");
    49           sendMessage.onclick=function(){
    50               var message= document.getElementById('MessageUN').value;
    51               //我们之前会有一个唯一的标识符,就是在click to start之前的标识符
    52               webSocket.send(message);
    53               //上边一部完成之后,会自动触发onmessage事件
    54           }
    55           
    56       }
    57       
    58       
    59        function start() {
    60          webSocket.send(name.value+" : "+'hello');
    61        }
    62 
    63       function onError(event) {
    64             alert(event.data);
    65       }
    66       
    67       webSocket.onerror = function(event) {
    68             onError(event)
    69       };
    70 
    71       webSocket.onopen = function(event) {
    72             onOpen(event)
    73       };
    74 
    75       webSocket.onmessage = function(event) {
    76             onMessage(event)
    77       };      
    78         
    79   }
    80   
    81   </script>
    82 </body>
    83 </html>
    
    

    重要的只有两个文件:chat.java以及chat.html,实现的是一个微型聊天室,当有用户连接近来和发送消息,所有都能看到。

     
     
  • 相关阅读:
    当今的架构师和架构
    外企2
    测试驱动开发TDD系列
    在IIS中部署WCF中遇到的问题
    设计高可用和高负载的网站系统(转载)
    IIS中部署WCF
    无限级分类1
    读《WCF技术剖析》(卷一)
    无限极列表2
    TCP/IP、HTTP、WEBSERVICE、SOAP、ICE都使用后才有感慨
  • 原文地址:https://www.cnblogs.com/yoissee/p/5903306.html
Copyright © 2020-2023  润新知