zoukankan      html  css  js  c++  java
  • Web开发相关笔记 #04# WebSocket

    本文的主要内容:

    1. HTTP VS. WebSocket
    2. WebSocket 的客户端实现(JavaScript)
    3. WebSocket 的服务端实现(Java & apache WebSocketAPI)
    4. WebSocket 深入学习

    HTTP VS. WebSocket

    简单来讲, WebSocket 就是一种允许服务端主动向客户端 PUSH 数据的技术。

    传统的 HTTP 只能是客户端先主动向服务器发起请求然后获得服务器响应。

    WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
    
    在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
    
    浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
    
    当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

    上面是网络上对于 websocket 的一段简短介绍。

    值得一提的是,有不少人认为 websocket (于2011年被IETF定为标准RFC 6455)是一项可以取代 AJAX (约 1998 年前后得到应用)的技术。

    简单的草图(。。自己画的不太极不严谨,例如说ws最开始有个 HTTP 验证漏掉了。。但是可以表达大概意思吧):

    然后是我收集的一些关于 websocket 的资料:

    1、WebSocket - Wikipedia 比较权威、全面

    2、An Introduction to WebSockets - Treehouse Blog 生动的个人博客

    3、websocket.org - Powered by Kaazing 以 websocket 为主题的网站!(websocket.org - WebSocket technology, demos, articles, and products.)

    4、菜鸟教程之 websocket  赶时间的看这个。

    总而言之,websocket 非常强大,应用也非常多,例如说可以用来构建基于浏览器的网页游戏、即时聊天工具之类的。

    顺便收藏(主题无关 ~ ):

    What's the difference between getRequestURI and getPathInfo methods in HttpServletRequest?

    WebSocket 的客户端实现(JavaScript)

    客户端代码完全拷贝自上面列出来的资料二

     index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>WebSockets Demo</title>
    
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
    <div id="page-wrapper">
        <h1>WebSockets Demo</h1>
    
        <div id="status">Connecting...</div>
    
        <ul id="messages"></ul>
    
        <form id="message-form" action="#" method="post">
            <textarea id="message" placeholder="Write your message here..." required></textarea>
            <button type="submit">Send Message</button>
            <button type="button" id="close">Close Connection</button>
        </form>
    </div>
    
    <script src="app.js"></script>
    </body>
    </html>

    /

    style.css

    *, *:before, *:after {
        -moz-box-sizing: border-box;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    }
    
    html {
        font-family: Helvetica, Arial, sans-serif;
        font-size: 100%;
        background: #333;
    }
    
    #page-wrapper {
        width: 650px;
        background: #FFF;
        padding: 1em;
        margin: 1em auto;
        border-top: 5px solid #69c773;
        box-shadow: 0 2px 10px rgba(0,0,0,0.8);
    }
    
    h1 {
        margin-top: 0;
    }
    
    #status {
        font-size: 0.9rem;
        margin-bottom: 1rem;
    }
    
    .open {
        color: green;
    }
    
    .closed {
        color: red;
    }
    
    
    ul {
        list-style: none;
        margin: 0;
        padding: 0;
        font-size: 0.95rem;
    }
    
    ul li {
        padding: 0.5rem 0.75rem;
        border-bottom: 1px solid #EEE;
    }
    
    ul li:first-child {
        border-top: 1px solid #EEE;
    }
    
    ul li span {
        display: inline-block;
        width: 90px;
        font-weight: bold;
        color: #999;
        font-size: 0.7rem;
        text-transform: uppercase;
        letter-spacing: 1px;
    }
    
    .sent {
        background-color: #F7F7F7;
    }
    
    .received {}
    
    #message-form {
        margin-top: 1.5rem;
    }
    
    textarea {
        width: 100%;
        padding: 0.5rem;
        font-size: 1rem;
        border: 1px solid #D9D9D9;
        border-radius: 3px;
        box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
        min-height: 100px;
        margin-bottom: 1rem;
    }
    
    button {
        display: inline-block;
        border-radius: 3px;
        border: none;
        font-size: 0.9rem;
        padding: 0.6rem 1em;
        color: white;
        margin: 0 0.25rem;
        text-align: center;
        background: #BABABA;
        border-bottom: 1px solid #999;
    }
    
    button[type="submit"] {
        background: #86b32d;
        border-bottom: 1px solid #5d7d1f;
    }
    
    button:hover {
        opacity: 0.75;
        cursor: pointer;
    }
    View Code

    /

    app.js

    window.onload = function() {
    
        // Get references to elements on the page.
        var form = document.getElementById('message-form');
        var messageField = document.getElementById('message');
        var messagesList = document.getElementById('messages');
        var socketStatus = document.getElementById('status');
        var closeBtn = document.getElementById('close');
    
        // The rest of the code in this tutorial will go here...
        // Create a new WebSocket.
        var socket = new WebSocket('ws://echo.websocket.org');
    
        // Show a connected message when the WebSocket is opened.
        socket.onopen = function(event) {
            socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;
            socketStatus.className = 'open';
        };
    
        // Handle any errors that occur.
        socket.onerror = function(error) {
            console.log('WebSocket Error: ' + error);
        };
    
        // Send a message when the form is submitted.
        form.onsubmit = function(e) {
            e.preventDefault();
    
            // Retrieve the message from the textarea.
            var message = messageField.value;
    
            // Send the message through the WebSocket.
            socket.send(message);
    
            // Add the message to the messages list.
            messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
                '</li>';
    
            // Clear out the message field.
            messageField.value = '';
    
            return false;
        };
    
        // Handle messages sent by the server.
        socket.onmessage = function(event) {
            var message = event.data;
            messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
                message + '</li>';
        };
    
        // Show a disconnected message when the WebSocket is closed.
        socket.onclose = function(event) {
            socketStatus.innerHTML = 'Disconnected from WebSocket.';
            socketStatus.className = 'closed';
        };
    
        // Close the WebSocket connection when the close button is clicked.
        closeBtn.onclick = function(e) {
            e.preventDefault();
    
            // Close the WebSocket.
            socket.close();
    
            return false;
        };
    };

     /

    直接把 三个文件放在同一个目录下,用浏览器打开 index.html 就可以用了。连接的是代码原作者的 websocket 服务器。

    WebSocket 的服务端实现(Java & apache WebSocketAPI)

    构建WebSocket 服务器的方式有很多,不过我只会用 tomcat 的 API,代码即是 Tomcat 的 websocket example 相比自己写的肯定要规范些。↓

     

    /*
     *  Licensed to the Apache Software Foundation (ASF) under one or more
     *  contributor license agreements.  See the NOTICE file distributed with
     *  this work for additional information regarding copyright ownership.
     *  The ASF licenses this file to You under the Apache License, Version 2.0
     *  (the "License"); you may not use this file except in compliance with
     *  the License.  You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     *  Unless required by applicable law or agreed to in writing, software
     *  distributed under the License is distributed on an "AS IS" BASIS,
     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *  See the License for the specific language governing permissions and
     *  limitations under the License.
     */
    package org.sample.web;
    
    import java.io.IOException;
    import java.util.Set;
    import java.util.concurrent.CopyOnWriteArraySet;
    import java.util.concurrent.atomic.AtomicInteger;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    @ServerEndpoint(value = "/websocket")
    public class ChatAnnotation {
    
        private static final String GUEST_PREFIX = "Guest";
        private static final AtomicInteger connectionIds = new AtomicInteger(0);
        private static final Set<ChatAnnotation> connections =
                new CopyOnWriteArraySet<>();
    
        private final String nickname;
        private Session session;
    
        public ChatAnnotation() {
            nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
        }
    
    
        @OnOpen
        public void start(Session session) {
            this.session = session;
            connections.add(this);
            String message = String.format("* %s %s", nickname, "has joined.");
            broadcast(message);
        }
    
    
        @OnClose
        public void end() {
            connections.remove(this);
            String message = String.format("* %s %s",
                    nickname, "has disconnected.");
            broadcast(message);
        }
    
    
        @OnMessage
        public void incoming(String message) {
            // Never trust the client
            String filteredMessage = String.format("%s: %s",
                    nickname, message.toString());
            broadcast(filteredMessage);
        }
    
    
    
    
        @OnError
        public void onError(Throwable t) throws Throwable {
        }
    
    
        private static void broadcast(String msg) {
            for (ChatAnnotation client : connections) {
                try {
                    synchronized (client) {
                        client.session.getBasicRemote().sendText(msg);
                    }
                } catch (IOException e) {
                    connections.remove(client);
                    try {
                        client.session.close();
                    } catch (IOException e1) {
                        // Ignore
                    }
                    String message = String.format("* %s %s",
                            client.nickname, "has been disconnected.");
                    broadcast(message);
                }
            }
        }
    }

     在运行之前需要修改 app.js 中的地址:

        // The rest of the code in this tutorial will go here...
        // Create a new WebSocket.
        var socket = new WebSocket('ws://localhost:8080/websocket');

    WebSocket 深入学习

    当然,上面仅用到了 WebSocket API 的一个小子集,要想真正用好这些 API 并没那么简单。下面是我找到的一些学习资料(基本上看 URL 就知道什么内容了):

    1、https://docs.oracle.com/javaee/7/api/javax/websocket/package-summary.html

    2、https://docs.oracle.com/javaee/7/tutorial/websocket.htm

    3、http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html

    4、https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java 

    5、http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/HomeWebsocket/WebsocketHome.html

    6、http://www.baeldung.com/java-websockets

    7、https://tomcat.apache.org/tomcat-9.0-doc/websocketapi/index.html

    8、https://benas.github.io/2016/02/21/using-the-java-api-for-webSocket-to-create-a-chat-server.html

  • 相关阅读:
    有道翻译js解密(1)
    Python面试题之Python正则表达式re模块
    go语言从例子开始之Example4.常量
    go语言从例子开始之Example3.变量
    go语言从例子开始之Example2.类型
    go语言从例子开始之Example1.helloworld
    python模块打补丁
    gevent协程之猴子补丁带来的坑
    charles抓包小程序
    httptesting HTTP(s)接口自动化测试框架
  • 原文地址:https://www.cnblogs.com/xkxf/p/9101853.html
Copyright © 2011-2022 走看看