zoukankan      html  css  js  c++  java
  • WebSocket 示例

    websocket应运而生

    在WebSocket规范提出之前,开发人员若要实现带有即时通信、实时数据、订阅推送等功能的应用实时性较强的功能,经常会使用的解决方法是 Comet。

    Comet是一种服务器向页面推送数据的技术。 有两种实现 Comet 的方式: 长轮询。长轮询是传统轮询(也称为短轮询)的一个翻版,即浏览

    器定时向服务器发送请求,看有没有更新的数据。图 展示的是短轮询的时间线。

                                           图1
    长轮询把短轮询颠倒了一下。页面发起一个到服务器的请求,然后服务器一直保持连接打开,直到
    有数据可发送。发送完数据之后,浏览器关闭连接,随即又发起一个到服务器的新请求。这一过程在页
    面打开期间一直持续不断。图 2 展示了长轮询的时间线。

                 图2

    无论是短轮询还是长轮询,浏览器都要在接收数据之前,先发起对服务器的连接。两者最大的区别在于服务器如何发送数据。

    短轮询是服务器立即发送响应,无论数据是否有效,而长轮询是等待发送响应。

    轮询的优势是所有浏览器都支持,因为使用 XHR 对象和 setTimeout()就能实现。而你要做的就是决定什么时候发送请求。

    第二种流行的 Comet 实现是 HTTP 流。流不同于上述两种轮询,因为它在页面的整个生命周期内只
    使用一个 HTTP 连接。具体来说,就是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周
    期性地向浏览器发送数据。

    这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。

    伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,Web Sockets 的目标是在一个单独的持久连接上提供全双工、双向通信。在 JavaScript 中创建了 Web Socket 之后,会有一个 HTTP 请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会使用 HTTP 升级从 HTTP 协议交换为 Web

    Socket 协议。也就是说,使用标准的 HTTP 服务器无法实现 Web Sockets只有支持这种协议的专门服
    务器才能正常工作。
     

     websocket 示例

     

     客户端(Web主页)代码:

    复制代码
     1 <%@ page language="java" pageEncoding="UTF-8" %>
     2 <!DOCTYPE html>
     3 <html>
     4 <head>
     5     <title>Java后端WebSocket的Tomcat实现</title>
     6 </head>
     7 <body>
     8     Welcome<br/><input id="text" type="text"/>
     9     <button onclick="send()">发送消息</button>
    10     <hr/>
    11     <button onclick="closeWebSocket()">关闭WebSocket连接</button>
    12     <hr/>
    13     <div id="message"></div>
    14 </body>
    15 
    16 <script type="text/javascript">
    17     var websocket = null;
    18     //判断当前浏览器是否支持WebSocket
    19     if ('WebSocket' in window) {
    20         websocket = new WebSocket("ws://localhost:8080/websocket");
    21     }
    22     else {
    23         alert('当前浏览器 Not support websocket')
    24     }
    25 
    26     //连接发生错误的回调方法
    27     websocket.onerror = function () {
    28         setMessageInnerHTML("WebSocket连接发生错误");
    29     };
    30 
    31     //连接成功建立的回调方法
    32     websocket.onopen = function () {
    33         setMessageInnerHTML("WebSocket连接成功");
    34     }
    35 
    36     //接收到消息的回调方法
    37     websocket.onmessage = function (event) {
    38         setMessageInnerHTML(event.data);
    39     }
    40 
    41     //连接关闭的回调方法
    42     websocket.onclose = function () {
    43         setMessageInnerHTML("WebSocket连接关闭");
    44     }
    45 
    46     //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    47     window.onbeforeunload = function () {
    48         closeWebSocket();
    49     }
    50 
    51     //将消息显示在网页上
    52     function setMessageInnerHTML(innerHTML) {
    53         document.getElementById('message').innerHTML += innerHTML + '<br/>';
    54     }
    55 
    56     //关闭WebSocket连接
    57     function closeWebSocket() {
    58         websocket.close();
    59     }
    60 
    61     //发送消息
    62     function send() {
    63         var message = document.getElementById('text').value;
    64         websocket.send(message);
    65     }
    66 </script>
    67 </html>
    复制代码

      Java Web后端代码

    复制代码
     1 package me.gacl.websocket;
     2 
     3 import java.io.IOException;
     4 import java.util.concurrent.CopyOnWriteArraySet;
     5 
     6 import javax.websocket.*;
     7 import javax.websocket.server.ServerEndpoint;
     8 
     9 /**
    10  * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
    11  * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
    12  */
    13 @ServerEndpoint("/websocket")
    14 public class WebSocketTest {
    15     //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    16     private static int onlineCount = 0;
    17 
    18     //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    19     private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
    20 
    21     //与某个客户端的连接会话,需要通过它来给客户端发送数据
    22     private Session session;
    23 
    24     /**
    25      * 连接建立成功调用的方法
    26      * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
    27      */
    28     @OnOpen
    29     public void onOpen(Session session){
    30         this.session = session;
    31         webSocketSet.add(this);     //加入set中
    32         addOnlineCount();           //在线数加1
    33         System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    34     }
    35 
    36     /**
    37      * 连接关闭调用的方法
    38      */
    39     @OnClose
    40     public void onClose(){
    41         webSocketSet.remove(this);  //从set中删除
    42         subOnlineCount();           //在线数减1
    43         System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    44     }
    45 
    46     /**
    47      * 收到客户端消息后调用的方法
    48      * @param message 客户端发送过来的消息
    49      * @param session 可选的参数
    50      */
    51     @OnMessage
    52     public void onMessage(String message, Session session) {
    53         System.out.println("来自客户端的消息:" + message);
    54         //群发消息
    55         for(WebSocketTest item: webSocketSet){
    56             try {
    57                 item.sendMessage(message);
    58             } catch (IOException e) {
    59                 e.printStackTrace();
    60                 continue;
    61             }
    62         }
    63     }
    64 
    65     /**
    66      * 发生错误时调用
    67      * @param session
    68      * @param error
    69      */
    70     @OnError
    71     public void onError(Session session, Throwable error){
    72         System.out.println("发生错误");
    73         error.printStackTrace();
    74     }
    75 
    76     /**
    77      * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
    78      * @param message
    79      * @throws IOException
    80      */
    81     public void sendMessage(String message) throws IOException{
    82         this.session.getBasicRemote().sendText(message);
    83         //this.session.getAsyncRemote().sendText(message);
    84     }
    85 
    86     public static synchronized int getOnlineCount() {
    87         return onlineCount;
    88     }
    89 
    90     public static synchronized void addOnlineCount() {
    91         WebSocketTest.onlineCount++;
    92     }
    93 
    94     public static synchronized void subOnlineCount() {
    95         WebSocketTest.onlineCount--;
    96     }
    97 }
    复制代码

     运行效果

      

     参考博客来源:http://www.cnblogs.com/xdp-gacl/p/5193279.html

  • 相关阅读:
    Spring Boot ELK Kafka 自定义断路器Circuit-Breaker
    据库主体在该数据库中拥有架构,无法删除解决方法
    AlloyImage
    引用嵌入式DLL方法
    C# C++ 字符串传递
    高效取图片像素的方法
    Microsoft Active Accessibility
    IIS配置支持APK下载
    C# gettime实现
    android快捷键
  • 原文地址:https://www.cnblogs.com/sunTin/p/8075237.html
Copyright © 2011-2022 走看看