中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用WebSocket網絡通信協議開發聊天室

發布時間:2021-10-19 11:28:08 來源:億速云 閱讀:131 作者:iii 欄目:web開發

本篇內容主要講解“如何使用WebSocket網絡通信協議開發聊天室”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何使用WebSocket網絡通信協議開發聊天室”吧!

了解WebSocket

開發聊天室,我們需要用到WebSocket這個網絡通信協議,那么為什么會用到它呢?

我們首先來引用阮一峰大佬的一篇文章一段話:

  • 初次接觸 WebSocket 的人,都會問同樣的問題:我們已經有了 HTTP 協議,為什么還需要另一個協議?它能帶來什么好處?

  • 答案很簡單,因為 HTTP 協議有一個缺陷:通信只能由客戶端發起。

  • 舉例來說,我們想了解今天的天氣,只能是客戶端向服務器發出請求,服務器返回查詢結果。HTTP 協議做不到服務器主動向客戶端推送信息。

  • 這種單向請求的特點,注定了如果服務器有連續的狀態變化,客戶端要獲知就非常麻煩。我們只能使用"輪詢":每隔一段時候,就發出一個詢問,了解服務器有沒有新的信息。最典型的場景就是聊天室。

  • 輪詢的效率低,非常浪費資源(因為必須不停連接,或者 HTTP 連接始終打開)。因此,工程師們一直在思考,有沒有更好的方法。WebSocket  就是這樣發明的。

我們來借用MDN網站上的官方介紹總結一下:

WebSockets  是一種先進的技術。它可以在用戶的瀏覽器和服務器之間打開交互式通信會話。使用此API,您可以向服務器發送消息并接收事件驅動的響應,而無需通過輪詢服務器的方式以獲得響應。

WebSocket 協議在2008年誕生,2011年成為國際標準。

WebSocket特點

服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種。

建立在 TCP 協議之上,服務器端的實現比較容易。

與 HTTP 協議有著良好的兼容性。默認端口也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP  代理服務器。

數據格式比較輕量,性能開銷小,通信高效。

可以發送文本,也可以發送二進制數據。

沒有同源限制,客戶端可以與任意服務器通信。

協議標識符是ws(如果加密,則為wss),即ws對應http,wss對應https。服務器網址就是  URL。即ws://www.xx.com或wss://www.xx.com

WebSocket客戶端常用API

WebSocket 對象提供了用于創建和管理 WebSocket連接,以及可以通過該連接發送和接收數據的 API。

使用WebSocket()構造函數來構造一個WebSocket 。

屬性

1.WebSocket.onopen

用于指定連接成功后的回調函數。

2.WebSocket.onmessage

用于指定當從服務器接受到信息時的回調函數。

3.WebSocket.onclose

用于指定連接關閉后的回調函數。

4.WebSocket.onerror

用于指定連接失敗后的回調函數。

方法

1.WebSocket.close()

關閉當前鏈接。

2.WebSocket.send(data)

客戶端發送數據到服務器,對要傳輸的數據進行排隊。

客戶端舉例

// Create WebSocket connection. const socket = new WebSocket('ws://localhost:8080'); // 這里的地址是服務器的websocket服務地址  // Connection opened socket.onopen = function(evt) {    console.log("Connection open ...");    ws.send("Hello WebSockets!"); };  // Listen for messages socket.onmessage = function(evt) {   console.log( "Received Message: " + evt.data);   socket.close(); };  // Connection closed socket.onclose = function(evt) {   console.log("Connection closed."); };

常用的WebSocket服務端

這里服務端我們使用Node.js,這里向大家介紹幾個常用的庫。

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. ws

  3. socket.io

  4. nodejs-websocket

具體用法,大家可以上網瀏覽詳細文檔,這里就不一一介紹啦。不過在這篇文章中。我將會給大家使用ws與nodejs-websocket這兩個模塊來分別進行項目開發。

客戶端與服務端都介紹完啦!我們就趕快行動起來吧!

開發本地端(或局域網)聊天室(第一種)

我們將基于Vue.js@3.0開發聊天室,原因是擁抱新技術。怎么搭建vue腳手架,這里就不介紹了,想必大家也會。我們直接就上代碼。

客戶端

<template>   <div class="home">     <div class="count">       <p>在線人數:{{ count }}</p>     </div>     <div class="content">       <div class="chat-box" ref="chatBox">         <div           v-for="(item, index) in chatArr"           :key="index"           class="chat-item"         >           <div v-if="item.name === name" class="chat-msg mine">             <p class="msg mineBg">{{ item.txt }}</p>             <p class="user" :style="{ background: bg }">               {{ item.name.substring(item.name.length - 5, item.name.length) }}             </p>           </div>           <div v-else class="chat-msg other">             <p class="user" :style="{ background: item.bg }">               {{ item.name.substring(item.name.length - 5, item.name.length) }}             </p>             <p class="msg otherBg">{{ item.txt }}</p>           </div>         </div>       </div>     </div>     <div class="footer">       <textarea         placeholder="說點什么..."         v-model="textValue"         autofocus         ref="texta"         @keyup.enter="send"       ></textarea>       <div class="send-box">         <p class="send active" @click="send">發送</p>       </div>     </div>   </div> </template>  <script> import { onMounted, onUnmounted, ref, reactive, nextTick } from "vue"; export default {   name: "Home",   setup() {     let socket = null;     const path = "ws://localhost:3000/"; // 本地服務器地址     const textValue = ref("");     const chatBox = ref(null);     const texta = ref(null);     const count = ref(0);     const name = new Date().getTime().toString();     const bg = randomRgb();     const chatArr = reactive([]);     function init() {       if (typeof WebSocket === "undefined") {         alert("您的瀏覽器不支持socket");       } else {         socket = new WebSocket(path);         socket.onopen = open;         socket.onerror = error;         socket.onclose = closed;         socket.onmessage = getMessage;         window.onbeforeunload = function(e) {           e = e || window.event;           if (e) {             e.returnValue = "關閉提示";             socket.close();           }           socket.close();           return "關閉提示";         };       }     }     function open() {       alert("socket連接成功");     }     function error() {       alert("連接錯誤");     }     function closed() {       alert("socket關閉");     }     async function getMessage(msg) {       if (typeof JSON.parse(msg.data) === "number") {         console.log(JSON.parse(msg.data));         count.value = msg.data;       } else {         const obj = JSON.parse(msg.data);         chatArr.push(obj);       }       await nextTick();       chatBox.value.scrollTop = chatBox.value.scrollHeight;     }     function randomRgb() {       let R = Math.floor(Math.random() * 130 + 110);       let G = Math.floor(Math.random() * 130 + 110);       let B = Math.floor(Math.random() * 130 + 110);       return "rgb(" + R + "," + G + "," + B + ")";     }     function send() {       if (textValue.value.trim().length > 0) {         const obj = {           name: name,           txt: textValue.value,           bg: bg,         };         socket.send(JSON.stringify(obj));         textValue.value = "";         texta.value.focus();       }     }     function close() {       alert("socket已經關閉");     }     onMounted(() => {       init();     });     onUnmounted(() => {       socket.onclose = close;     });     return {       send,       textValue,       chatArr,       name,       bg,       chatBox,       texta,       randomRgb,       count,     };   }, }; </script>

至于樣式文件,這里我也貼出來。

html,body{   background-color: #e8e8e8;   user-select: none; } ::-webkit-scrollbar {   width: 8px;   height: 8px;   display: none; } ::-webkit-scrollbar-thumb {   background-color: #D1D1D1;   border-radius: 3px;   -webkit-border-radius: 3px;   border-left: 2px solid transparent;   border-top: 2px solid transparent; } *{   margin: 0;   padding: 0; } .mine {   justify-content: flex-end; } .other {   justify-content: flex-start; } .mineBg {   background: #98e165; } .otherBg {   background: #fff; } .home {   position: fixed;   top: 0;   left: 50%;   transform: translateX(-50%);   width: 100%;   height: 100%;   min-width: 360px;   min-height: 430px;   box-shadow: 0 0 24px 0 rgb(19 70 80 / 25%); } .count{   height: 5%;   display: flex;   justify-content: center;   align-items: center;   background: #EEEAE8;   font-size: 16px; } .content {   width: 100%;   height: 80%;   background-color: #f4f4f4;   overflow: hidden; } .footer {   position: fixed;   bottom: 0;   width: 100%;   height: 15%;   background-color: #fff; } .footer textarea {   width: 100%;   height: 50%;   background: #fff;   border: 0;   box-sizing: border-box;   resize: none;   outline: none;   padding: 10px;   font-size: 16px; } .send-box {   display: flex;   height: 40%;   justify-content: flex-end;   align-items: center; } .send {   margin-right: 20px;   cursor: pointer;   border-radius: 3px;   background: #f5f5f5;   z-index: 21;   font-size: 16px;   padding: 8px 20px; } .send:hover {   filter: brightness(110%); } .active {   background: #98e165;   color: #fff; } .chat-box {   height: 100%;   padding:0 20px;   overflow-y: auto; } .chat-msg {   display: flex;   align-items: center; } .user {   font-weight: bold;   color: #fff;   position: relative;   word-wrap: break-word;   box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);   width: 60px;   height: 60px;   line-height: 60px;   border-radius:8px ;   text-align: center; } .msg {   margin: 0 5px;   max-width: 74%;   white-space: normal;   word-break: break-all;   color: #333;   border-radius: 8px;   padding: 10px;   text-align: justify;   font-size: 16px;   box-shadow: 0px 0px 10px #f4f4f4; } .chat-item {   margin: 20px 0;   animation: up-down 1s both; } @keyframes up-down {   0% {     opacity: 0;     transform: translate3d(0, 20px, 0);   }    100% {     opacity: 1;     transform: none;   } }

服務端

這里使用的是Node.js。

nodejs-websocket:websocket服務器和客戶端的nodejs模塊。

const ws = require("nodejs-websocket"); const server = ws.createServer((conn) => {   conn.on("text", (str) => {     broadcast(str);   });   conn.on("error", (err) => {     console.log(err);   }); }); server.listen(3000, function () {   console.log("open"); }); // 群發消息 function broadcast(data) {   server.connections.forEach((conn) => {     conn.sendText(data);   }); }

項目一覽

如何使用WebSocket網絡通信協議開發聊天室

在線人數為零,這不是bug,是因為當時在本地端沒有做,只是放上了這個版塊。不過,在云服務端我已經放上了這個功能。那么,我們來看一下吧。

開發云端聊天室(第二種)

客戶端&zwj;

<template>   <div class="home">     <div class="count">       <p>在線人數:{{ count }}</p>     </div>     <div class="content">       <div class="chat-box" ref="chatBox">         <div           v-for="(item, index) in chatArr"           :key="index"           class="chat-item"         >           <div v-if="item.name === name" class="chat-msg mine">             <p class="msg mineBg">{{ item.txt }}</p>             <p class="user" :style="{ background: bg }">               {{ item.name.substring(item.name.length - 5, item.name.length) }}             </p>           </div>           <div v-else class="chat-msg other">             <p class="user" :style="{ background: item.bg }">               {{ item.name.substring(item.name.length - 5, item.name.length) }}             </p>             <p class="msg otherBg">{{ item.txt }}</p>           </div>         </div>       </div>     </div>     <div class="footer">       <textarea         placeholder="說點什么..."         v-model="textValue"         autofocus         ref="texta"         @keyup.enter="send"       ></textarea>       <div class="send-box">         <p class="send active" @click="send">發送</p>       </div>     </div>   </div> </template>  <script> import { onMounted, onUnmounted, ref, reactive, nextTick } from "vue"; export default {   name: "Home",   setup() {     let socket = null;     const path = "wss:/xxx.com/wsline/"; // 這個網址只是測試網址,這里只是說明云服務地址     const textValue = ref("");     const chatBox = ref(null);     const texta = ref(null);     const count = ref(0);     const name = new Date().getTime().toString();     const bg = randomRgb();     const chatArr = reactive([]);     function init() {       if (typeof WebSocket === "undefined") {         alert("您的瀏覽器不支持socket");       } else {         socket = new WebSocket(path);         socket.onopen = open;         socket.onerror = error;         socket.onclose = closed;         socket.onmessage = getMessage;         window.onbeforeunload = function(e) {           e = e || window.event;           if (e) {             e.returnValue = "關閉提示";             socket.close();           }           socket.close();           return "關閉提示";         };       }     }     function open() {       alert("socket連接成功");     }     function error() {       alert("連接錯誤");     }     function closed() {       alert("socket關閉");     }     async function getMessage(msg) {       if (typeof JSON.parse(msg.data) === "number") {         console.log(JSON.parse(msg.data));         count.value = msg.data;       } else {         const obj = JSON.parse(msg.data);         chatArr.push(obj);       }       await nextTick();       chatBox.value.scrollTop = chatBox.value.scrollHeight;     }     function randomRgb() {       let R = Math.floor(Math.random() * 130 + 110);       let G = Math.floor(Math.random() * 130 + 110);       let B = Math.floor(Math.random() * 130 + 110);       return "rgb(" + R + "," + G + "," + B + ")";     }     function send() {       if (textValue.value.trim().length > 0) {         const obj = {           name: name,           txt: textValue.value,           bg: bg,         };         socket.send(JSON.stringify(obj));         textValue.value = "";         texta.value.focus();       }     }     function close() {       alert("socket已經關閉");     }     onMounted(() => {       init();     });     onUnmounted(() => {       socket.onclose = close;     });     return {       send,       textValue,       chatArr,       name,       bg,       chatBox,       texta,       randomRgb,       count,     };   }, }; </script>

樣式文件同本地端樣式,可以查看上方的代碼。

服務端

這里我使用了ws模塊,并且我也搭建了https服務器,并使用了更為安全的wss協議。接下來,我們來看下是怎么操作的。

const fs = require("fs"); const httpServ = require("https"); const WebSocketServer = require("ws").Server; // 引用Server類  const cfg = {   port: 3456,   ssl_key: "../../https/xxx.key", // 配置https所需的文件2   ssl_cert: "../../https/xxx.crt", // 配置https所需的文件1 };  // 創建request請求監聽器 const processRequest = (req, res) => {   res.writeHead(200);   res.end("Websocket linked successfully"); };  const app = httpServ   .createServer(     {       // 向server傳遞key和cert參數       key: fs.readFileSync(cfg.ssl_key),       cert: fs.readFileSync(cfg.ssl_cert),     },     processRequest   )   .listen(cfg.port);  // 實例化WebSocket服務器 const wss = new WebSocketServer({   server: app, }); // 群發 wss.broadcast = function broadcast(data) {     wss.clients.forEach(function each(client) {       client.send(data);     }); }; // 如果有WebSocket請求接入,wss對象可以響應connection事件來處理 wss.on("connection", (wsConnect) => {   console.log("Server monitoring");   wss.broadcast(wss._server._connections);   wsConnect.on("message", (message) => {     wss.broadcast(message);   });   wsConnect.on("close", function close() {     console.log("disconnected");     wss.broadcast(wss._server._connections);   }); });

我們在云服務上啟動命令。

啟動成功!

 如何使用WebSocket網絡通信協議開發聊天室

這里還沒有結束,因為你使用的是ip地址端口,必須轉發到域名上。所以我使用的nginx進行轉發,配置如下參數。

location /wsline/ {      proxy_pass https://xxx:3456/;      proxy_http_version 1.1;      proxy_set_header Upgrade $http_upgrade;      proxy_set_header Connection "Upgrade";      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;      proxy_set_header Host $http_host;      proxy_set_header X-Real-IP $remote_addr;      proxy_set_header X-Forwarded-Proto https;      proxy_redirect off; }

那么,重啟云端服務器,看下效果。

項目一覽

 如何使用WebSocket網絡通信協議開發聊天室

那么,到這里一款云端聊天室就這么做成了,可以實時顯示在線人數,這樣你就可以知道有多少人在這里跟你聊天。

到此,相信大家對“如何使用WebSocket網絡通信協議開發聊天室”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

江山市| 都昌县| 莱西市| 红安县| 新龙县| 罗江县| 荃湾区| 南汇区| 都匀市| 涟水县| 巴中市| 阿拉善盟| 澄迈县| 沂源县| 晴隆县| 宾阳县| 大同市| 萝北县| 仪征市| 大竹县| 眉山市| 大姚县| 理塘县| 沅陵县| 白朗县| 保靖县| 义乌市| 宣威市| 定结县| 宜章县| 阳东县| 额济纳旗| 千阳县| 永仁县| 苏尼特右旗| 周至县| 太康县| 淳安县| 象州县| 肃宁县| 柘城县|