Введение
Веб-сокеты определяют способ связи по сети через один сокет.полнодуплексный канал связи. Просто постепенное улучшение по сравнению с традиционной связью HTTP, особенно дляВ режиме реального времени, управляемый событиямиПриложение — это шаг вперед. Путем сравнения Polling (опрос), Long-Polling (длинный опрос), Websocket и sse. Четыре технологии обмена мгновенными сообщениями в Интернете, сравнивающие ихМетод реализацииа такжеПреимущества и недостатки каждого. Сравнительные преимущества и недостатки заключаются в следующем:
| # | Опрос | Долгий опрос | Websocket | sse |
|---|---|---|---|---|
| письмо-соглашение | http | http | tcp | http |
| Метод триггера | клиент (клиент) | клиент (клиент) | клиент, сервер (клиент, сервер) | клиент, сервер (клиент, сервер) |
| преимущество | Хорошая совместимость, сильная отказоустойчивость, простая реализация | Экономит ресурсы по сравнению с коротким опросом | Полнодуплексный протокол связи, низкая производительность, высокий уровень безопасности и масштабируемость. | Простая реализация и низкая стоимость разработки |
| недостаток | Плохая безопасность, учитывая больше ресурсов памяти и количества запросов | Плохая безопасность, занимающая больше ресурсов памяти и запросов | Передача данных требует вторичного анализа, что увеличивает стоимость и сложность разработки. | Только для продвинутых браузеров |
| Задерживать | Не в режиме реального времени, задержка зависит от интервала запроса | то же, что короткий опрос | в реальном времени | Не в реальном времени, задержка по умолчанию 3 секунды, задержку можно настроить |
Вышеупомянутое в основном включает реализацию каждогопреимуществоа такженедостаток, на чем они основаныпротокол, к тому концуинициативаотправить данные.
Опрос
Короткий опрос (опрос)Идея реализациисторона браузеракаждые несколько секунд доСервис-терминалОтправьте http-запрос, и сервер ответит сразу после получения запроса, независимо от того, есть ли обновление данных.Когда ответ сервера будет завершен, соединение TCP будет закрыто.,Как показано ниже:
Пример кода реализован следующим образом:
function Polling() {
fetch(url).then(data => {
// somthing
}).catch(err => {
console.log(err);
});
}
setInterval(polling, 5000);
- Преимущества: Как видите, реализация очень проста, еесовместимостьТакже лучше, покаПоддержка http-протоколаможно достичь таким образом.
- Недостатки: Но очевиден и его недостаток, что он очень сильно потребляет ресурсы, т.к.
TcpСоединение очень ресурсоемкое, и сервер закроет его, когда ответ будет завершен.Tcpсоединение, следующий запрос устанавливается сноваTcpсоединять.
COMET
**Алекс Рассел (руководитель проекта Dojo Toolkit)** говорит, что это основано наHTTP长连接, Технология «проталкивания сервера», которая не требует установки плагинов на стороне браузера,“Comet”.
Обычно используемые COMET делятся на два типа:Технология длительного опроса на основе HTTP и режим потока с длинным соединением на основе iframe..
Долгий опрос
После того, как клиент отправит запрос, серверне сразуВозвращает данные, сервер будетзапрос на блокировкусоединение не будетОтключить немедленно, пока на стороне сервераОбновление данных или тайм-аут соединенияТолько после возвращения клиент снова отправляет запрос на создание нового соединения и так далее для получения последних данных. Общий эффект таков:
Код клиента выглядит следующим образом:
function LongPolling() {
fetch(url).then(data => {
LongPolling();
}).catch(err => {
LongPolling();
console.log(err);
});
}
LongPolling();
- Преимущества: по сравнению с коротким опросом, длинный опрос значительно уменьшает количество ненужных HTTP-запросов и по сравнению с этим экономит ресурсы.
- Недостаток: зависание соединения также может привести к пустой трате ресурсов.
режим длинного потока соединения (потока) на основе iframe
Когда мы встраиваем iframe в страницу и устанавливаем его src, сервер может «непрерывно» выводить контент клиенту через длинное соединение.
Например, мы можем вернуть сегмент клиентуscriptэтикетка завернутаjavascriptcode, код будет выполняться в iframe. Поэтому, если мы предварительноiframeФункция-обработчик process() определена на родительской странице , и каждый раз, когда необходимо отправить новые данные, она записывается в ответе соединения. Затем этот код в iframe вызовет предопределенную функцию process() на родительской странице. (Это немного похоже на то, как JSONP передает данные?)
// 在父页面中定义的数据处理方法
function process(data) {
// do something
}
// 创建不可见的iframe
var iframe = document.createElement('iframe');
iframe.style = 'display: none';
// src指向后端接口
iframe.src = '/long_iframe';
document.body.appendChild(iframe);
Бэкэнд по-прежнему использует узел в качестве примера
const app = http.createServer((req, res) => {
// 返回数据的方法,将数据拼装成script脚本返回给iframe
const iframeSend = data => {
let script = `<script type="text/javascript">
parent.process(${JSON.stringify(data)})
</script>`;
res.write(script);
};
res.setHeader('connection', 'keep-alive');
// 注意设置相应头的content-type
res.setHeader('content-type', 'text/html; charset=utf-8');
// 当有数据更新时,服务端“推送”数据给客户端
EVENT.addListener(MSG_POST, iframeSend);
req.socket.on('close', () => {
console.log('iframe socket close');
// 注意在连接关闭时移除监听,避免内存泄露
EVENT.removeListener(MSG_POST, iframeSend);
});
});
Эффект следующий:
Однако в использовании iframe есть небольшой недостаток, поэтому этот iframe эквивалентен тому, что он никогда не загружается, поэтому в браузере всегда будет флаг загрузки.
Его плюсы и минусы такие же, как и у длинного опроса выше.
Websocket
Некоторые функции и основные принципы использования WebSocket не будут здесь повторяться, см. другой блог.Веб-сокет (1) Анализ; Примерный код выглядит следующим образом:Сервер
const express = require('express');
const app = express();
const server = require('http').Server(app);
const WebSocket = require('ws');
const wss = new WebSocket.Server({port: 8080});
wss.on('connection', function connection(ws) {
console.log('server: receive connection');
ws.on('message', function incoming(message) {
console.log('server: recevied: %s', message);
});
ws.send('world');
});
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.listen(3000);
клиент
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
console.log('ws onopen');
ws.send('from client:hello');
};
ws.onmessage = function (e) {
console.log('ws onmessage');
console.log('from server:' + e.data);
}
Эффект операции следующий:
- Преимущества: нет потери производительности
- Недостаток: изучение нового набора библиотек запросов
SSE (Server-Sent Events)
Server-SentдаHTML5Придумайте стандарт. Создается между клиентом и серверомTCPподключиться, тои поддерживать эту связь, пока клиент или сервер не отключится,ServerSentИспользуется механизм «спросить» + «ответить».После установления соединения браузер будет периодически отправлять сообщение на сервер, чтобы спросить, есть ли у него собственное сообщение. Принцип его реализации аналогичен тому, что мы упоминали в предыдущем разделе.режим длинного соединения на основе iframe.
Содержимое ответа HTTP имеет специальныйcontent-type —— text/event-stream, заголовок ответа идентифицирует содержимое ответа какпоток событий, клиентне закроет соединение, но подождите, пока сервер будет непрерывно отправлять результаты ответа.
Спецификация SSE относительно проста и в основном делится на две части: объект EventSource в браузере и соединение между серверной и браузерной сторонами.Протокол.
Основное использование
Этот объект может быть создан в браузере через конструктор Vectorource
var source = new EventSource('/sse');
а такжеSSEСодержимое ответа можно рассматривать какпоток событий, состоящий из разных событий. Эти события запускают внешний интерфейсEventSourceметоды на объектах.
// 默认的事件
source.addEventListener('message', function (e) {
console.log(e.data);
}, false);
// 用户自定义的事件名
source.addEventListener('my_msg', function (e) {
process(e.data);
}, false);
// 监听连接打开
source.addEventListener('open', function (e) {
console.log('open sse');
}, false);
// 监听错误
source.addEventListener('error', function (e) {
console.log('error');
});
EventSource работает, прослушивая события. Обратите внимание, что приведенный выше код прослушивает событие y_msg, SSE поддерживает пользовательские события, а событие по умолчанию получает данные, прослушивая сообщение. Код реализации выглядит следующим образом:
клиент
// 显示聊天信息
let chat = new EventSource("/chat-room");
chat.onmessage = function (event) {
let msg = event.data;
$(".list-group").append("<li class='list-group-item'>" + msg + "</li>");
// chat.close(); 关闭server-sent event
};
// 自定义事件
chat.addEventListener("myChatEvent", function (event) {
let msg = event.data;
$(".list-group").append("<li class='list-group-item'>" + msg + "</li>");
});
серверные ноды
var express = require('express');
var router = express.Router();
router.get('/chat-room', function (req, res, next) {
// 当res.white的数据data 以\n\n结束时 就默认该次消息发送完成,触发onmessage方法,以\r\n不会触发onmessage方法
res.header({
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
// res.white("event: myChatEvent\r\n"); 自定义事件
res.write("retry: 10000\r\n"); // 指定通信的最大间隔时间
res.write("data: start~~\n\n");
res.end(); // 不加end不会认为本次数据传输结束 会导致不会有下一次请求
});
- Преимущества: клиенту нужно подключиться только один раз, и сервер будет регулярно нажимать его, если только один конец не отключится. И SSE автоматически переподключится, когда соединение неожиданно прервется.
- Недостаток: чтобы выучить новую грамматику
Суммировать
Сравнение вышеупомянутых четырех технологий обмена мгновенными сообщениями в Интернете можно рассматривать с разных точек зрения, и их приоритеты различны.В основном их можно разделить на две категории на основеhttpа такжеtcpОдин из двух видов общения.
Вопросы совместимости: короткий опрос > длинный опрос > длинное соединение SSE > WebSocket
Учитывайте производительность: WebSocket > Длинное соединение SSE > Длинный опрос > Короткий опрос
Пуш сервера: WebSocket> Длинное соединение SSE> Длинный опрос
Ссылаться на
Различные принципы и примеры технологии "Server Push" (опрос/COMET/SSE/WebSocket)