zoukankan      html  css  js  c++  java
  • WebSocket介绍和一个简单的聊天室

    WebSocket是什么呢?

      WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范,WebSocketAPI被W3C定为标准。

    WebSocket 是独立的、创建在 TCP 上的协议,和 HTTP 的唯一关联是使用 HTTP 协议的101状态码进行协议切换,使用的 TCP 端口是80,可以用于绕过大多数防火墙的限制。

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

    目前常见的浏览器如 Chrome、IE、Firefox、Safari、Opera 等都支持 WebSocket,同时需要服务端程序支持 WebSocket。

        --------------------------------------------------------------------------------------

    以上摘自wiki,总的来说websocket实现了服务器和浏览器之间的双向通信,摆脱了以往的一问一答的通信方式,可以自由地传输数据.

    Websocket有什么优点?

    • 由于没有http头信息,所以传输的数据包很小
    • 服务器可以主动推送信息

    Websocket的握手协议

    还是照搬wiki上的例子,websocket在建立连接时,浏览器会向服务器发出如下请求

    GET / HTTP/1.1
    Upgrade: websocket
    Connection: Upgrade
    Host: example.com
    Origin: null
    Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
    Sec-WebSocket-Version: 13

    这段请求会告诉服务器即将切换到websocket协议,如果服务器支持的话,会返回如下信息

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
    Sec-WebSocket-Origin: null
    Sec-WebSocket-Location: ws://example.com/

    至此,握手阶段完成,服务器和浏览器之间可以开始发送和接收信息

    使用Websocket实现一个简单的网页聊天室

    • 使用tomcat8的websocket-api
    • 参考tomcat自带的example

    服务器端ChatServlet

    package com.yc.chatroom;
    import java.io.IOException;
    import java.util.Set;
    import java.util.concurrent.CopyOnWriteArraySet;
    import java.util.concurrent.atomic.AtomicInteger;
    import javax.servlet.annotation.WebServlet;
    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/chat")//指定客户端连接地址
    public class ChatServlet {
      private static final long serialVersionUID = 1L;
      private static final String GUEST_PREFIX = "Guest";
      private static final AtomicInteger connectionIds = new AtomicInteger(0);
      private static final Set<ChatServlet> connections = new CopyOnWriteArraySet<ChatServlet>();
      private final String nickname;
      private Session session;
      public ChatServlet() {
        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 {
        t.printStackTrace();
      }
      private static void broadcast(String msg) {
        for (ChatServlet 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);
          }
        }
      }
    }

    浏览器端index.jsp

    <%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <html>
    <head>
    <title>Apache Tomcat WebSocket Examples: Chat</title>
    <style type="text/css">
    input#chat {
       410px
    }
    #console-container {
       400px;
    }
    #console {
      border: 1px solid #CCCCCC;
      border-right-color: #999999;
      border-bottom-color: #999999;
      height: 170px;
      overflow-y: scroll;
      padding: 5px;
       100%;
    }
    #console p {
      padding: 0;
      margin: 0;
    }
    </style>
    </head>
    <body>
      <div>
        <p>
          <input type="text" placeholder="type and press enter to chat"
            id="chat" />
        </p>
        <div id="console-container">
          <div id="console"></div>
        </div>
      </div>
    </body>
    <script type="text/javascript">
      /**
      *  指定要连接的websocket地址
      *  如果使用https,则使用wss://
      **/
      var socket = new WebSocket('ws://' + window.location.host+ '/chatroom/websocket/chat');
      
      //连接与服务器的连接
      socket.onopen = function() {
        showMsg('Info: WebSocket connection opened.');
        document.getElementById('chat').onkeydown = function(event) {
          if (event.keyCode == 13) {
            sendMsg();
          }
        };
      };
      //断开与服务器的连接
      socket.onclose = function() {
        document.getElementById('chat').onkeydown = null;
        showMsg('Info: WebSocket closed.');
      };
      //与服务器之间的通信
      socket.onmessage = function(message) {
        showMsg(message.data);
      };
      //显示消息
      function showMsg(message) {
        var console = document.getElementById('console');
        var p = document.createElement('p');
        p.style.wordWrap = 'break-word';
        p.innerHTML = message;
        console.appendChild(p);
        while (console.childNodes.length > 25) {
          console.removeChild(console.firstChild);
        }
        console.scrollTop = console.scrollHeight;
      }
      //发送消息
      function sendMsg() {
        var message = document.getElementById('chat').value;
        if (message != '') {
          socket.send(message);
          document.getElementById('chat').value = '';
        }
      }
    </script>

    运行结果

    一次打开两个窗口,用户依次为guest0, guest1

    guest0:

    guest1:

    guest0退出:

    原文链接地址:https://mssora.com/websocket-intro-and-chatroom/

  • 相关阅读:
    字符串处理(包括正则生成工具)
    php.ini 个别字段笔记
    php-5.4 升级到 php7.2
    【mysql笔记】针对 group_concat 长度限制
    七牛,前端上传图片
    PHP 替换 特殊空白符
    【代码块】定时任务<swoole> 100%无人值守
    安装nodejs
    linux安装beanstalkd
    个人笔记上传 -- redis安装
  • 原文地址:https://www.cnblogs.com/huozf/p/6237484.html
Copyright © 2011-2022 走看看