zoukankan      html  css  js  c++  java
  • 初识websocket及java服务端的简单实现

    概念:WebSocket是一种在单个TCP连接上进行全双工通信的协议。

    WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

    背景:很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

    而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。

    在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

    websocket运用场景:

    1. 即时通讯:多媒体聊天,你可以使用该技术开个聊天室,聊个火热。可以单独2人聊个畅快。
    2. 互动游戏:现在多人游戏越来越火热,那么多人游戏必须是时时的,不考虑其他因素,只是时效性方面,也可以用该技术做多人游戏。
    3. 协同合作:开发人员会有git,svn等代码管理工具,但还是会有冲突。用此技术开发一个文档协同编辑工具,使每个人的编辑内容都时时同步,将不会有冲突发生。
    4. 动态数据表报:类似通知变更,如有需求,可以开发一个时时的数据报表,使用此技术,服务端数据发生变化,可在表报上立刻显示出来。如,电商平台的交易数据,每时每刻都在变化着,可以时时监控。
    5. 实时工具:如导航,实时查询工具等也可使用。

    原理

    WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接。我们来看看WebSocket连接是如何创建的。

    首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

    GET ws://localhost:3000/ws/chat HTTP/1.1
    Host: localhost
    Upgrade: websocket
    Connection: Upgrade
    Origin: http://localhost:3000
    Sec-WebSocket-Key: client-random-string
    Sec-WebSocket-Version: 13

    该请求和普通的HTTP请求有几点不同:

    1. GET请求的地址不是类似/path/,而是以ws://开头的地址;
    2. 请求头Upgrade: websocket和Connection: Upgrade表示这个连接将要被转换为WebSocket连接;
    3. Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;
    4. Sec-WebSocket-Version指定了WebSocket的协议版本。

    随后,服务器如果接受该请求,就会返回如下响应:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: server-random-string

    该响应代码101表示本次连接的HTTP协议即将被更改,更改后的协议就是Upgrade: websocket指定的WebSocket协议。

    为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)

    版本号和子协议规定了双方能理解的数据格式,以及是否支持压缩等等。如果仅使用WebSocket的API,就不需要关心这些。

    现在,一个WebSocket连接就建立成功,浏览器和服务器就可以随时主动发送消息给对方。消息有两种,一种是文本,一种是二进制数据。通常,我们可以发送JSON格式的文本,这样,在浏览器处理起来就十分容易。

    为什么WebSocket连接可以实现全双工通信而HTTP连接不行呢?实际上HTTP协议是建立在TCP协议之上的,TCP协议本身就实现了全双工通信,但是HTTP协议的请求-应答机制限制了全双工通信。WebSocket连接建立以后,其实只是简单规定了一下:接下来,咱们通信就不使用HTTP协议了,直接互相发数据吧。

    HTTP协议与websocket协议对比:

     

    WebSocket目前支持两种统一资源标志符ws和wss,类似于HTTP和HTTPS。

     

    浏览器支持:

    很显然,要支持WebSocket通信,浏览器得支持这个协议,这样才能发出ws://xxx的请求。目前,支持WebSocket的主流浏览器如下:

    • Chrome
    • Firefox
    • IE >= 10
    • Sarafi >= 6
    • Android >= 4.4
    • iOS >= 8

     

    客户端简单实现:

    新建websocket.html

     

    <!DOCTYPE HTML>
    <html>
       <head>
       <meta charset="utf-8">
       <title>websocket 客户端</title>
        
          <script type="text/javascript">
             function WebSocketTest()
             {
                if ("WebSocket" in window)
                {
                   alert("您的浏览器支持 WebSocket!");
                   
                   // 创建一个 websocket
                   var ws = new WebSocket("ws://localhost:8887");
                    
                   ws.onopen = function()
                   {
                      // Web Socket 已连接上,使用 send() 方法发送数据
                      ws.send("发送数据");
                      alert("数据发送中...");
                   };
                    
                   ws.onmessage = function (evt) 
                   { 
                      var received_msg = evt.data;
                      alert("数据已接收...");
                   };
                    
                   ws.onclose = function()
                   { 
                      // 关闭 websocket
                      alert("连接已关闭..."); 
                   };
                }
                
                else
                {
                   // 浏览器不支持 WebSocket
                   alert("您的浏览器不支持 WebSocket!");
                }
             }
          </script>
            
       </head>
       <body>
       
          <div id="sse">
             <a href="javascript:WebSocketTest()">运行 WebSocket</a>
          </div>
          
       </body>
    </html>

     

     

    客户端API:

    WebSocket 属性

    以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

    属性

    描述

    Socket.readyState

    只读属性 readyState 表示连接状态,可以是以下值:

    0 - 表示连接尚未建立。

    1 - 表示连接已建立,可以进行通信。

    2 - 表示连接正在进行关闭。

    3 - 表示连接已经关闭或者连接不能打开。

    Socket.bufferedAmount

    只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    WebSocket 事件

    以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

    事件

    事件处理程序

    描述

    open

    Socket.onopen

    连接建立时触发

    message

    Socket.onmessage

    客户端接收服务端数据时触发

    error

    Socket.onerror

    通信发生错误时触发

    close

    Socket.onclose

    连接关闭时触发

    WebSocket 方法

    以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

    方法

    描述

    Socket.send()

    使用连接发送数据

    Socket.close()

    关闭连接

     

    JAVA 服务端实现:

    maven依赖

    <dependency>
      <groupId>org.java-websocket</groupId>
      <artifactId>Java-WebSocket</artifactId>
      <version>1.4.0</version>
    </dependency>
    

      

     

    服务端示例:ServerDemo.java

    import org.java_websocket.WebSocket;
    import org.java_websocket.handshake.ClientHandshake;
    import org.java_websocket.server.WebSocketServer;
    
    import java.net.InetSocketAddress;
    import java.net.UnknownHostException;
    
    /**
     * @Author 99514925@qq.com
     * @Create 2020/2/3 23:03
     **/
    public class ServerDemo extends WebSocketServer {
    
    
        public ServerDemo() throws UnknownHostException {
        }
    
        public ServerDemo(int port) throws UnknownHostException {
            super(new InetSocketAddress(port));
            System.out.println("websocket Server start at port:"+port);
        }
    
    
        /**
         * 触发连接事件
         */
        @Override
        public void onOpen(WebSocket conn, ClientHandshake clientHandshake) {
            System.out.println("new connection ===" + conn.getRemoteSocketAddress().getAddress().getHostAddress());
        }
    
        /**
         *
         * 连接断开时触发关闭事件
         */
        @Override
        public void onClose(WebSocket conn, int code, String reason, boolean remote) {
    
        }
    
        /**
         * 客户端发送消息到服务器时触发事件
         */
        @Override
        public void onMessage(WebSocket conn, String message) {
            System.out.println("you have a new message: "+ message);
            //向客户端发送消息
            conn.send(message);
        }
    
        /**
         * 触发异常事件
         */
        @Override
        public void onError(WebSocket conn, Exception e) {
            //e.printStackTrace();
            if( conn != null ) {
                //some errors like port binding failed may not be assignable to a specific websocket
            }
        }
    
        /**
         * 启动服务端
         * @param args
         * @throws UnknownHostException
         */
        public static void main(String[] args) throws UnknownHostException {
            new ServerDemo(8887).start();
        }
    }

     

     

    由于WebSocket是一个协议,服务器具体怎么实现,取决于所用编程语言和框架本身。

     

  • 相关阅读:
    机器学习--k-means聚类原理
    机器学习--朴素贝叶斯模型原理
    关联分析原理小结
    批发经销商客户价值细分
    员工离职预测
    共享单车租赁需求预测
    蓝桥杯 区间k大数查询
    蓝桥杯 猴子吃包子
    java计算程序运行时间
    leetcode 185周周赛 字节专场
  • 原文地址:https://www.cnblogs.com/qq99514925/p/12258036.html
Copyright © 2011-2022 走看看