菜鳥教程-WebSocket實時通信
一、WebSocket概念
- WebSocket是HTML5提供的一種瀏覽器與服務器進行全雙工通訊的網路技術,屬于應用層協議,它基于TCP傳輸協議,并復用HTTP的握手通道,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接, 并進行雙向資料傳輸,WebSocket 的出現就解決了半雙工通信的弊端,它最大的特點是:服務器可以向客戶端主動推動訊息,客戶端也可以主動向服務器推送訊息,

二、WebSocket原理
- 客戶端向 WebSocket 服務器通知(notify)一個帶有所有接收者ID(recipients IDs)的事件(event),服務器接收后立即通知所有活躍的(active)客戶端,只有ID在接收者ID序列中的客戶端才會處理這個事件,
三、WebSocket特點
- 支持雙向通信,實時性更強,相對于HTTP請求需要等待客戶端發起請求服務端才能回應,延遲明顯更少
- 可以發送文本,也可以發送二進制資料
- 建立在TCP協議之上,服務端的實作比較容易
- 資料格式比較輕量,性能開銷小,通信高效
- 沒有同源限制,客戶端可以與任意服務器通信
- 協議識別符號是ws(如果加密,則為wss),服務器網址就是 URL
- 與 HTTP 協議有著良好的兼容性,默認埠也是80和443,并且握手階段采用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理服務器
四、WebSocket應用場景
- 彈幕
- 媒體聊天
- 協同編輯
- 基于位置的應用
- 體育實況更新
- 股票基金報價實時更新
五、Websocket基本使用
在HTML5中,瀏覽器已經實作了websocket的API,直接使用即可,
WebSocket-MDN
六、創建Websocket物件
// 引數1: url:連接的websocket屬性
// 引數2: protocol,可選的,指定連接的協議
// var socket = new WebSocket('ws://echo.websocket.org')
var Socket = new WebSocket(url, [protocol] );
七、Websocket事件
| 事件 | 事件處理程式 | 描述 |
|---|---|---|
| open | Socket.onopen | 連接建立時觸發 |
| message | Socket.onmessage | 客戶端接收服務端資料時觸發 |
| error | Socket.onerror | 通信發生錯誤時觸發 |
| close | Socket.onclose | 連接關閉時觸發 |
八、Websocket方法
| 方法 | 描述 |
|---|---|
| Socket.send() | 使用連接發送資料 |
| Socket.close() | 關閉連接 |
使用nodejs開發websocket服務
我們剛剛使用了官網提供的echo服務,接下來我們自己通過nodejs實作一個簡單的websocket服務,
使用nodejs開發websocket需要依賴一個第三方包,Nodejs Websocket
專案搭建
新建一個websocket server端的專案
mkdir server-demo
cd server-demo
yarn init -y
yarn add nodejs-websocket
touch app.js
開發服務程式
在app.js中
// 匯入第三方模塊
const ws = require('nodejs-websocket')
// websocket占用的埠號
const PORT = 3000
const server = ws.createServer(connect => {
console.log('新的連接')
// 接收到客戶端的文本內容時觸發
connect.on('text', str => {
console.log('接收:' + str)
// 把接收到的字串轉換成大寫,并且給客戶端回應
connect.sendText(str.toUpperCase() + '!!!!')
})
// 監聽關閉事件
connect.on('close', () => {
console.log('連接關閉了')
})
// 監聽錯誤事件, 比如瀏覽器關閉了連接,或者發送的資料格式不對等
connect.on('error', err => {
console.log('連接例外')
})
})
// 啟動websocket服務
server.listen(PORT, function() {
console.log(`websocket server listening on ${PORT}`)
})
啟動服務
node app.js
在終端中看到websocket server listening on 3000就說明webserver服務啟動成功了
進行測驗
修改客戶端中index.js檔案中的連接地址,重新進行測驗
// 創建websocket物件,地址已經修改稱為了自己撰寫的地址
const URL = 'ws://localhost:3000'
const websocket = new WebSocket(URL)
九、案例-Websocket開發聊天室程式
app.js
const ws = require('nodejs-websocket')
const PORT = 3000
const TYPE_MSG = 0
const TYPE_ENTER = 1
const TYPE_LEAVE = 2
let userCount = 0
const server = ws.createServer(connect => {
console.log('有新用戶連接了')
// 每次有新用戶連接,需要給所有用戶發送一條新增用戶的訊息
userCount++
connect.userName = 'user' + userCount
// 給所有的用戶進行廣播
broadcast({
type: TYPE_ENTER,
msg: connect.userName + '進入了聊天室',
date: new Date().toLocaleTimeString()
})
connect.on('text', msg => {
// 如果接收到用戶的資料, 需要發送給所有的用戶
broadcast({
type: TYPE_MSG,
msg: msg,
date: new Date().toLocaleTimeString()
})
})
connect.on('close', () => {
console.log('用戶斷開連接')
userCount--
// 給所有的用戶發送一條用戶離開的訊息
broadcast({
type: TYPE_LEAVE,
msg: `${connect.userName}離開了聊天室`,
date: new Date().toLocaleTimeString()
})
})
connect.on('error', () => {
console.log('連接失敗')
})
})
function broadcast(msg) {
server.connections.forEach(conn => {
conn.sendText(JSON.stringify(msg))
})
}
server.listen(PORT, () => {
console.log('服務器啟動成功了', PORT)
})
index.html
<!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>Document</title>
<style>
/* div {
width: 200px;
height: 200px;
border: 1px solid #000;
} */
</style>
</head>
<body>
<!-- 用于收集輸入內容 -->
<input type="text" placeholder="請輸入需要發送的內容" />
<!-- 用于發送websocket請求 -->
<button>websocket測驗</button>
<!-- 用于顯示websock服務器的回應 -->
<div ></div>
<script>
var input = document.querySelector('input')
var button = document.querySelector('button')
var div = document.querySelector('div')
// 1. 創建websocket物件, 這個地址是官方提供的地址
// var socket = new WebSocket('ws://echo.websocket.org')
var socket = new WebSocket('ws://localhost:3000')
// 2. 給websocket注冊事件
socket.addEventListener('open', function() {
// 與服務端建立連接的時候觸發
div.innerText = '恭喜你,與服務端建立連接了'
})
// 如何給服務器發送訊息
button.addEventListener('click', function() {
socket.send(input.value)
input.valuehttps://www.cnblogs.com/P1Kaj1uu/archive/2022/10/10/= ''
})
// 如果接收服務器的資料
socket.addEventListener('message', function(e) {
var data = https://www.cnblogs.com/P1Kaj1uu/archive/2022/10/10/JSON.parse(e.data)
var dv = document.createElement('div')
dv.innerHTML = data.msg + '----' + data.date
if (data.type === 0) {
dv.style.color = 'green'
}
if (data.type === 1) {
dv.style.color = 'red'
}
if (data.type === 2) {
dv.style.color = 'gray'
}
div.appendChild(dv)
})
socket.addEventListener('close', () => {
div.innerHTML = '與服務器斷開連接'
})
</script>
</body>
</html>
如果使用原生的websocket進行開發,會比較麻煩,比如支持的事件太少,發送的資料只能是字串格式的,提供的api也很少,類似于廣播這種方法都沒有,需要自己封裝,
十、socket.io基本使用
socketio
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513071.html
標籤:其他
