написать впереди
webSocket — это технология, которая позволяет серверу активно передавать данные клиенту. Функция журнала была написана несколько дней назад, и данные журнала необходимо обновлять в режиме реального времени. Бывает, что в проекте есть упакованный компонент WebSocket, а интерфейс поддерживает webSocket, поэтому он реализован. Это также первый раз, когда я использую его, я просто исследовал его и поделился им. Пример кода статьи находится здесь:GitHub.com/Nero Метод Nero использует…
Что такое веб-сокет
Прежде всего, вам нужно понять концепцию веб-сокета, следующее объяснение из Википедии
WebSocket — это протокол связи, обеспечивающий полнодуплексную связь по одному TCP-соединению. WebSocket упрощает обмен данными между клиентом и сервером, Позволяет серверу активно передавать данные клиенту. В WebSocket API браузеру и серверу нужно выполнить рукопожатие только один раз, и между ними может быть установлено постоянное соединение. И двусторонняя передача данных.
Прежде всего, необходимо понимать, что WebSocket — это протокол связи, отличный от протокола HTTP, который может реализовать только однократную передачу запроса клиента и ответа сервера. WebSocket может реализовать двустороннюю связь между клиентом и сервером.Проще говоря, самое большое и очевидное отличие заключается в том, что сервер может активно отправлять сообщения клиенту. Остальные особенности:
- На этапе рукопожатия используется протокол HTTP.
- Формат данных является легким и имеет низкую производительность. Когда клиент и сервер обмениваются данными, заголовок пакета данных от сервера к клиенту составляет всего от 2 до 10 байтов, а от клиента к серверу необходимо добавить еще одну 4-байтовую маску. HTTP должен каждый раз передавать полный заголовок.
- Улучшенная поддержка двоичных файлов, возможность отправки текста и двоичных данных.
- Нет ограничений по гомологии, любой клиент может общаться с сервером.
- Идентификатор протокола — ws (или wss, если он зашифрован), а запрошенный адрес — это внутренний API, поддерживающий веб-сокеты.
Несколько способов связи с сервером в реальном времени
Все мы знаем, что обычно есть два способа взаимодействия с сервером в режиме реального времени без использования WebSocket. Опрос AJAX и длинный опрос.
AJAX-опрос
Опрос AJAX заключается в отправке запросов через регулярные промежутки времени, то есть нормальный процесс связи между клиентом и сервером, но он отправляется в бесконечном цикле Таким образом, можно гарантировать, что как только сервер получит последние новости, он может быть получен клиентом. .
Длинный опрос
Long Polling长轮询是客户端和浏览器保持一个长连接,等服务端有消息返回,断开。 然后再重新连接,也是个循环的过程,无穷尽也。 . .
Клиент инициирует длительный опрос, и если у сервера нет данных для возврата, Он будет удерживать запрос, и когда будут данные, он будет возвращен клиенту. Клиент снова инициирует длительный опрос и снова повторяет описанный выше процесс.
недостаток
Вышеупомянутые два метода имеют фатальную слабость, накладные расходы слишком высоки, и они пассивны. Предполагая высокий параллелизм, это тест для сервера. Возможности одноразового рукопожатия WebSocket, постоянного соединения и активной отправки могут решить вышеуказанные проблемы без ущерба для производительности.
Процесс подключения через WebSocket
Клиент инициирует рукопожатие HTTP, сообщает серверу о необходимости связи с протоколом WebSocket и сообщает версию протокола WebSocket. Сервер подтверждает версию протокола и обновляет ее до протокола WebSocket. После этого, если есть данные, которые необходимо передать, они будут активно переданы клиенту.
Когда подключение начинается, клиент использует протокол HTTP и протокол обновления сервера. После завершения обновления последующая обмен данными последовала протокол WebSocket. Давайте посмотрим на запрос заголовки
Accept-Encoding: gzip, deflate, br
Accept-Language: zh,zh-TW;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6
Cache-Control: no-cache
Connection: Upgrade
Host: 127.0.0.1:3000
Origin: http://localhost:3000
Pragma: no-cache
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: bwb9SFiJONXhQ/A4pLaXIg==
Sec-WebSocket-Version: 13
Upgrade: websocket
Ключевые поля таковы:
- Соединение: Обновление означает обновление протокола
- Обновление: веб-сокет для обновления протокола до протокола веб-сокета.
- Sec-WebSocket-Version указывает версию веб-сокета. Если сервер не поддерживает версию, необходимо вернуть заголовок Sec-WebSocket-Version, который содержит номер версии, поддерживаемой сервером.
- Sec-WebSocket-Key соответствует Sec-WebSocket-Accept в заголовке ответа сервера.Поскольку нет ограничения на одно и то же происхождение, клиент веб-сокета может произвольно подключаться к службам, поддерживающим веб-сокет. Это эквивалентно ключу и замку, избегая избыточных, бессмысленных соединений.
Взгляните на заголовки ответов ответа сервера.
Connection: Upgrade
Sec-WebSocket-Accept: 2jrbCWSCPlzPtxarlGTp4Y8XD20=
Upgrade: websocket
Ключ это поле
- Sec-WebSocket-Accept: используется для информирования сервера о том, что он готов инициировать соединение через веб-сокет, значение рассчитывается в соответствии с ключом Sec-WebSocket-Key в заголовке клиентского запроса.
WebSocket API
Если клиент хочет связаться с сервером, который поддерживает webScoket, он может использовать конструктор WebSocket для возврата объекта WebSocket.
const ws = new WebSocket("ws://localhost:3000/websocket");
Таким образом, клиент начнет подключаться к серверу.
Свойства возвращенного экземпляра объекта:
- WebSocket.onopen: обратный вызов после успешного подключения
- WebSocket.onclose: обратный вызов после закрытия соединения
- WebSocket.onerror: после сбоя обратного вызова
- WebSocket.onmessage: клиент получает обратный вызов данных сервера
- webSocket.bufferedAmount: количество двоичных байтов, не отправленных на сервер.
- WebSocket.binaryType: используйте двоичный тип данных для подключения
- WebSocket.protocol : подчиненный протокол, выбранный сервером.
- WebSocket.url: абсолютный путь к WebSocket.
- WebSocket.readyState: текущее состояние соединения, соответствующее четырем константам.
имя | стоимость |
---|---|
WebSocket.CONNECTING | 0 |
WebSocket.OPEN | 1 |
WebSocket.CLOSING | 2 |
WebSocket.CLOSED | 3 |
метод:
- WebSocket.close() закрывает текущее соединение
- WebSocket.send(data) отправляет данные на сервер
Пример
После обсуждения стольких концепций я наконец-то понял, как их использовать. Реализация связи WebSocket требует сотрудничества клиента и сервера.
Написать пример, после того, как сервер запускает соединение, используйте таймер для активного отправки случайных номеров к клиенту, и клиент также может отправить на сообщение сервера. Затем сервер возвращает это сообщение клиенту. Клиент является JS + HTML, сервис реализован с Express + Express-WS. Код здесь:GitHub.com/Nero Метод Nero использует…. Вы можете клонировать его, установить зависимости и запустить npm start, чтобы увидеть эффект.
клиент
Передняя страница, окончательный эффект показан выше:
<body>
<div class="websocket">
<div class="receive">
<p>服务端返回的消息</p>
<div id="receive-box"></div>
</div>
<div class="send">
<textarea type="text" id="msg-need-send"></textarea>
<p>
<button id="send-btn">点击发消息给服务端</button>
</p>
</div>
<button id="exit">关闭连接</button>
</div>
</body>
js код для использования webSocket находится здесь. Все, что он делает, это привязывает события к элементам страницы. Затем создайте объект WebSocket, прослушивайте события, такие как подключение объекта, получение сообщений и закрытие, и отправляйте данные обратно на страницу.
const msgBox = document.getElementById("msg-need-send")
const sendBtn = document.getElementById("send-btn")
const exit = document.getElementById("exit")
const receiveBox = document.getElementById("receive-box")
// 创建一个webSocket对象
const ws = new WebSocket("ws://127.0.0.1:3000/websocket/test")
ws.onopen = e => {
// 连接后监听
console.log(`WebSocket 连接状态: ${ws.readyState}`)
}
ws.onmessage = data => {
// 当服务端返回数据的时候,放到页面里
receiveBox.innerHTML += `<p>${data.data}</p>`
receiveBox.scrollTo({
top: receiveBox.scrollHeight,
behavior: "smooth"
})
}
ws.onclose = data => {
// 监听连接关闭
console.log("WebSocket连接已关闭")
console.log(data);
}
sendBtn.onclick = () => {
// 点击发送按钮。将数据发送给服务端
ws.send(msgBox.value)
}
exit.onclick = () => {
// 客户端主动关闭连接
ws.close()
}
Сервер
С учетом модульной разработки прямо в файле нет кода, непосредственно создающего сервис. Вместо этого маршрутизация используется для назначения отдельного интерфейса службе webSocket.
const express = require("express");
const expressWs = require("express-ws")
const router = express.Router()
expressWs(router);
router.ws("/test", (ws, req) => {
ws.send("连接成功")
let interval
// 连接成功后使用定时器定时向客户端发送数据,同时要注意定时器执行的时机,要在连接开启状态下才可以发送数据
interval = setInterval(() => {
if (ws.readyState === ws.OPEN) {
ws.send(Math.random().toFixed(2))
} else {
clearInterval(interval)
}
}, 1000)
// 监听客户端发来的数据,直接将信息原封不动返回回去
ws.on("message", msg => {
ws.send(msg)
})
})
module.exports = router
Наконец, посмотрите на процесс взаимодействия данных
Суммировать
Вышеприведенное просто реализует связь через веб-сокет. Есть много практических вещей, таких как расширение webSocket, обнаружение сердцебиения, шифрование данных, аутентификация личности и другие точки знаний. Но мне также нужно изучить его самому, поэтому я не буду вводить его первым.
Статьи по Теме
Протокол WebSocket: 5 минут от входа до освоения
Учебное пособие по WebSocket - Жуан Ифэн
Добро пожаловать, чтобы обратить внимание на мою официальную учетную запись: один внешний интерфейс, один внешний интерфейс, я время от времени буду делиться знаниями о внешнем интерфейсе, которые я понимаю.