zoukankan      html  css  js  c++  java
  • websocket学习和群聊实现

    WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询。在此协议的基础上,可以实现前后端数据、多端数据,真正的实时响应。在学习WebSocket的过程中,实现了一个简化版群聊,过程和代码详细记录在这篇文章中。

    本篇文章来自董沅鑫的个人网站,引用、转载请指明出处

    查看更多知识,或者技术交流:请访问godbmw.com

    1 概述

    1.1 WebSocket 是什么?

    1. 建立在 TCP 协议之上的网络通信协议
    2. 全双工通信协议
    3. 没有同源限制
    4. 可以发送文本、二进制数据等

    1.2 为什么需要 WebSocket?

    了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

    这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

    因此,如果在客户端想实时监听服务器变化,必须使用 ajax 来进行轮询,效率低,浪费资源。

    而 websocket 就可以使得前后端进行全双工通信(两方都可以向对方进行数据推送),是真正的平等对话

    2 WebSocket 客户端

    支持HTML5的浏览器支持 WebSocket 协议:

    var ws = new WebSocket(url); // 创建一个websocket对象
    

    2.1 WebSocket 属性

    属性 描述
    ws.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
    ws.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    2.2 WebSocket 方法

    属性 描述
    ws.send() 数据发送
    ws.close() 关闭连接

    2.3 Websocket 事件

    属性 描述
    open 连接建立触发
    message 通信时触发
    error 出错触发
    close 关闭连接触发

    2.4 代码实现

    假设我们在本地8080端口打开了websocket服务,那么,下面代码可以在浏览器中实现和这个服务的通信:

    <body>
      <script>
        var ws = new WebSocket("ws://localhost:8080/");
        // 建立连接触发
        ws.onopen = function () {
          ws.send("open ws");
          console.log("open ws");
        };
    
        // 接收服务端数据触发
        ws.onmessage = function (evt) {
          var data = evt.data;
          console.log("Data is ", data);
        };
    
        // 断开连接触发
        ws.onclose = function () {
          console.log("close ws");
        };
      </script>
    </body>
    

    3 WebSocket 服务端

    关于服务端实现,根据技术选型不同,可以选用不同的库和包。我这里使用的是nodews库来websocket服务端。

    阮一峰的博文提到的socket.io库,在浏览器端的写法不兼容原生API,准确来说,它们自己实现了一套websocket。所以,使用的时候前后端都应该引用第三方库。这样就造成了代码迁移性,严重下降。

    综上所述,ws库有以下优点:

    1. 兼容性好,兼容浏览器原生API
    2. 长期维护,效果稳定
    3. 使用方便(往下看就知道了)

    4 实现群聊

    4.1 群聊 服务端实现

    首先,在命令行中,安装ws库: npm install ws --save

    现在,利用ws来实现一个监听8080端口的websocket服务器,讲解都在代码注释里,一目了然

    const PORT = 8080; // 监听端口
    const WebSocket = require("ws"); // 引入 ws 库
    
    const wss = new WebSocket.Server({ port: PORT }); // 声明wss对象
    
    /**
     * 向除了本身之外所有客户端发送消息,实现群聊功能
     * @param {*} data 要发送的数据
     * @param {*} ws 客户端连接对象
     */
    wss.broadcastToElse = function broadcast(data, ws) { 
      wss.clients.forEach(function each(client) {
        if (client !== ws && client.readyState === WebSocket.OPEN) {
          client.send(data);
        }
      });
    };
    
    /* 客户端接入,触发 connection */
    wss.on("connection", function connection(ws, req) {
      let ip = req.connection.remoteAddress; // 通过req对象可以获得客户端信息,比如:ip,headers等
    
      /* 客户端发送消息,触发 message */
      ws.on("message", function incoming(message) { 
        ws.send(message); // 向客户端发送消息
        wss.broadcastToElse(message, ws); // 向 其他的 客户端发送消息,实现群聊效果
      });
    
    });
    

    4.2 群聊 客户端实现

    为了方便编写,这里引入了jquerybootstrap这两个库,只需要关注js代码即可。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>群聊</title>
      <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
      <script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script>
    </head>
    <body>
      <div class="container">
        <textarea class="form-control" rows="30" disabled="disabled" id="show-area"></textarea>
        <input type="text" class="form-control" placeholder="请输入聊天内容" id="chat-input">
        <button type="button" class="btn btn-info" id="send-btn">发送</button>
      </div>
      <script>
        var userName = parseInt(Math.random() * 1000, 10) // 随机用户名, 以标识身份
        
        var sendBtn = $("#send-btn"), // 发送信息按钮
          chatInput = $("#chat-input"), // 聊天信息输入框
          showArea = $("#show-area") // 聊天信息展示框
    
        var ws = new WebSocket("ws://localhost:8080/") // 初始化WebSocket对象
    
        sendBtn.on("click", function () {
          var content = chatInput.val()
          if (content.length === 0) {
            return alert("请不要输入空白内容")
          }
          content = "At " + (new Date()).toString() + "
    " + "来自用户" + userName + "
    " + content // 拼接用户信息、时间信息和消息
          ws.send(content) // 发送消息
          chatInput.val("") // 清空输入框
        })
    
        ws.onopen = function () { console.log("Conncet open") }
        ws.onmessage = function (evt) {
          var data = evt.data
          showArea.val(showArea.val() + data + "
    
    ") // 刷新聊天信息展示框:显示群聊信息
        }
        ws.onclose = function () { console.log("Connect close") }
      </script>
    </body>
    </html>
    

    4.3 群聊 效果展示

    首先启动我们的服务端代码:node server.js 。其中,server.js是放置服务端代码的文件。

    然后,我们打开2次编写的html代码,这相当于,打开2个客户端。来检测群聊功能。

    效果图

    5. 相关资料

    本篇文章来自董沅鑫的个人网站,引用、转载请指明出处

    查看更多知识,或者技术交流:请访问godbmw

  • 相关阅读:
    三次请求(读-改-读)引出nibernate 一级缓存
    算法竞赛入门经典第一、二章摘记
    uva 10905 Children's Game
    uva 11205 The broken pedometer
    uva 10160 Servicing stations
    uva 208 Firetruck
    uva 167 The Sultan's Successors
    zoj 1016 Parencodings
    uva 307 Sticks
    uva 216 Getting in Line
  • 原文地址:https://www.cnblogs.com/geyouneihan/p/9502280.html
Copyright © 2011-2022 走看看