WebSocketТехнология постепенно совершенствовалась и принесла нам много удобства в производственной среде. В этой статье мы попытаемся сначала разъяснить основные принципы WebSocket, а затем описать, как его использовать на практике.
WebSocket не заменит полностью HTTP
Первое, что нужно прояснить, — это позиционирование WebSocket. WebSocket — это технология, основанная на HTTP, которая обеспечивает полнодуплексный обмен текстовыми и двоичными данными между клиентом и сервером. Здесь следует отметить несколько вещей:
- Построен на HTTP. WebSocket необходимо установить HTTP-соединение, прежде чем клиент сможет инициировать запрос «рукопожатия» WebSocket.После успешного рукопожатия клиент и сервер могут взаимодействовать с WebSocket.
- Обеспечить текст (текст) и двоичные данные (двоичные данные) два вида передачи данных
- Полнодуплексная связь. Как только коммуникационное соединение WebSocket установлено, будь то клиент или браузер, любая сторона может отправлять сообщения другой стороне, то есть реализуется функция проталкивания данных от сервера к клиенту.
WebSocket был создан для удовлетворения постоянно растущих требований к интернет-коммуникациям в режиме реального времени. В традиционном Интернете для реализации связи в реальном времени (например, в веб-версии QQ) обычным способом является опрос. Через определенные промежутки времени браузер отправляет HTTP-запросы на сервер, а затем возвращает последние данные в браузер. Наиболее очевидным недостатком этого метода является необходимость непрерывной отправки запросов, что не только занимает полосу пропускания, но и ресурсы ЦП сервера (запросы должны приниматься без информации).
С этой точки зрения появление WebSocket имеет как минимум два преимущества перед чистым HTTP для связи в реальном времени:
- Улучшена производительность в реальном времени. Пока установлено соединение WebSocket, состояние соединения может поддерживаться. При отправке сообщений не требуется дополнительный процесс установления соединения, и производительность связи в реальном времени значительно улучшена.
- Общий трафик данных уменьшается, а заголовок WebSocket намного меньше, чем заголовок HTTP, особенно количество отправляемых сообщений велико, что позволит сэкономить значительный объем трафика данных.
Однако в процессе реализации эффективной связи в реальном времени WebSocket больше не пользуется некоторыми услугами и оптимизациями, предоставляемыми браузерами, такими как управление состоянием, сжатие, кэширование и т. д. Неизвестно, будут ли производители браузеров делать какие-то сервисы и оптимизации для WebSocket в будущем, но, по крайней мере, на данный момент WebSocket недостаточно, чтобы пошатнуть статус HTTP. В целом, WebSocket компенсирует недостатки HTTP в некоторых областях связи, но он никогда не сможет полностью заменить HTTP.
WebSocket API
Первоначально являясь частью стандарта HTML5, WebSocket превратился в независимый стандарт протокола. На стороне клиента HTML5 предоставляет нам очень чистый API.
Метод строительства
WebSocket(url: string, protocols?: string[] | string)
- URL-адрес
表示要连接的 URL。注意协议名是
ws
илиwss
. - протоколы Может быть одной строкой имени протокола или массивом из нескольких строк имен протокола. Эти строки используются для представления подпротоколов, что позволяет серверу реализовать несколько подпротоколов WebSocket (например, вы можете указать разные протоколы для обработки разных типов взаимодействий). Если этот параметр не указан, по умолчанию будет пустая строка.
Метод прототипа
Всего их всего два.
close(code?: number, reason?: string): void
Закройте соединение WebSocket или остановите текущий запрос на соединение. Если состояние соединения уже закрыто, этот метод не действует.
- код Указывает номер состояния закрытого соединения, указывающий причину закрытия соединения. Если этот параметр не указан, значение по умолчанию равно 1000, что означает нормальное закрытие соединения. Посмотреть больше значенийCloseEventстраница.
- причина Описательная строка, указывающая, почему соединение было закрыто.
send(data: string | ArrayBuffer | Blob): void
Отправка данных на сервер через соединение WebSocket.
- data представляет данные для отправки на сервер, которые могут быть String,ArrayBufferилиBlobТипы. Строковый тип эквивалентен текстовым данным, ArrayBuffer и Blob — двоичным данным.
мероприятие
События следуют двум способам написания на родном Javascript:
onevent = handler
addEventListener(event, handler)
Поддерживаемые событияopen
,message
,close
а такжеerror
. Уведомлениеmessage
Событие срабатывает, когда все данные получены.
Атрибуты
Свойства объекта WebSocket используются для описания сведений о связи и состояния.
-
binaryType: string
Указывает тип содержимого, передаваемого в двоичном формате. Значение должно быть'blob'
или'arraybuffer'
var ws = new WebSocket('wss://example.com/socket'); ws.binaryType = "arraybuffer"; // 强制将接收的二进制数据转为 ArrayBuffer 类型 ws.onmessage = function(msg) { if(msg.data instanceof ArrayBuffer) { processArrayBuffer(msg.data); } else { processText(msg.data); } }
-
bufferedAmount: number
передачаsend()
Метод ставит в очередь многобайтовые данные для передачи, но еще не выдал их. Значение сбрасывается на 0 после отправки всех данных очереди. Он не будет установлен на 0, когда соединение будет закрыто. Если вы продолжаете звонитьsend()
, это значение будет продолжать расти. Только чтение. -
protocol: string
Строка, указывающая имя подпротокола, выбранного сервером. Значение этого свойства передается в конструкторprotocols
параметр или один из них. -
readyState: number
Текущее состояние соединения. Значение является одной из констант состояния готовности. Только чтение. -
url: string
URL-адрес, переданный в конструктор. Это должен быть абсолютный URL. Только чтение.
самый простой пример
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server', event.data);
});
Однако описанное выше реализовано только на клиентском веб-сокете, без взаимодействия с сервером веб-сокет не может обмениваться данными. Существуют различные схемы реализации WebSocket на стороне сервера, которые будут реализованы на Node.js в следующем разделе.
Вышеупомянутая часть является личным резюме, если вы хотите узнать больше о его API, вы можете обратиться к нему.Документация по MDN.
Базовое использование WebSocket
Использование WebSocket на самом деле не сложно, в этом разделе будут объединеныsocket.ioмодули объясняются. Давайте посмотрим, как создать простейшее приложение WebSocket.
Первый шаг — установить библиотеку зависимостей:
npm install socket.io express
Второй шаг, сборка клиента /public/index.html:
<body>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io('http://localhost:3231');
socket.on('connect', () => {
socket.emit('greet', 'Hello, websocket!');
socket.on('uppergreet', data => console.log(data));
});
</script>
</body>
Обратите внимание на способ представления socket.io выше, не сомневайтесь в правильности пути, потому что socket.io автоматически импортирует соответствующий клиентский код и выставитio
глобальные переменные.
Третий шаг, сборка сервера server.js:
const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
io.on('connection', socket => {
socket.on('greet', data => socket.emit('uppergreet', data.toUpperCase()));
});
http.listen(port, () => console.log('listening on port ' + port));
Наконец, запуститеnode server.js
и доступ к нему через браузерhttp://localhost:3000
, откройте консоль и вы увидите вывод:
HELLO, WEBSOCKET!
Можно заметить, что в методе написания с использованием socket.io для создания приложения WebSocket все еще существует большая разница по сравнению с API WebSocket, упомянутым в предыдущем разделе.
В дополнение к модулю socket.io, упомянутому в этом разделе, существуют различные реализации на Node.js, такие какwebsocketа такжеnodejs-websocket, они не только реализовали протокол связи WebSocket сервера, но и более-менее инкапсулировали WebSocket API клиента, о котором говорилось в предыдущем разделе, а функции были значительно улучшены, что нашло широкое применение в практической работе. сравнение Склоняюсь к библиотеке socket.io.
Применимые сценарии WebSocket
WebSocket подходит для сценариев, требующих эффективного общения в реальном времени, таких как веб-чат, боевые игры и т. д. В этом разделе будет использоватьсяsocket.ioМодули объясняются.На официальном сайте socket.io есть несколько типичных сценариев использования.Здесь мы используем более простой, предоставленный официальным сайтом.Корпус монтажной областиБыть объясненным. Официальный сайт socket.io также даетПример приложения для чата, разработанного с помощью jQuery, я реализовал в соответствии с его окончательным эффектомреактивная версия.
Ключевым моментом случая чертежной доски является то, что несколько клиентов могут рисовать на одной чертежной доске одновременно, и все клиенты могут видеть результаты рисования в режиме реального времени (пользователи могут видеть результаты рисования в режиме реального времени), это очень удобно использовать WebSocket здесь.
Первый — это серверный код index.js, который очень похож на код из предыдущего раздела:
const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const port = process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
io.on('connection', socket => {
socket.on('drawing', data => socket.broadcast.emit('drawing', data));
});
http.listen(port, () => console.log('listening on port ' + port));
Затем выполните следующую команду:
node index.js
Затем откройте оба окна браузера и посетитеhttp://localhost:3000
, а затем рисовать в одном браузере, а другой браузер может видеть результаты в режиме реального времени.
Вы можете видеть, что код на стороне сервера очень лаконичен, и ключевые шаги здесьconnection
Метод обработчика события внутри методаsocket
будет контролироватьdrawing
мероприятие, прослушиваниеdrawing
В callback-функции после события снова транслироватьdrawing
События, вещание означает, что они отправляются всем клиентам, подключенным к серверу.
Тогда есть код ключа клиента /public/main.js:
var socket = io();
socket.on('drawing', onDrawingEvent);
var canvas = document.getElementsByClassName('whiteboard')[0];
canvas.addEventListener('mousedown', onMouseDown, false);
canvas.addEventListener('mouseup', onMouseUp, false);
canvas.addEventListener('mouseout', onMouseUp, false);
canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false);
в коде вышеonDrawingEvent
,mouseUp
а такжеonMouseMove
Ключ вызывается внутри методаdrawLine
метод:
function drawLine(x0, y0, x1, y1, color, emit){
// ... 绘制 canvas ...
if (!emit) return;
socket.emit('drawing', {
// ... 绘制 canvas 的状态信息 ...
});
}
drawLine
метод в зависимости от поступающихemit
бит, чтобы определить, отправлять ли на серверdrawing
Событие, если оно нарисовано самим клиентом, отправить его на серверdrawing
событие, иначе нет.
Вышеизложенное является общей идеей реализации приложения реального времени, в котором несколько человек рисуют одновременно.Можно увидеть, что когда мы используем WebSocket для связи, особенно при использовании библиотеки инструментов с высокой степенью инкапсуляции, такой как socket.io, процесс коммуникации очень прост Мы можем вложить большую часть нашей энергии в бизнес-логику.
Развитие технологии WebSocket позволило разработчикам реализовать логику связи в реальном времени, не понимая внутренностей протокола, особенно при использовании Node.js в качестве сервера. Библиотека инструментов, аналогичная socket.io, предоставляет очень удобный инструмент как для сервера, и клиент Вызов метода очень быстрый, чтобы начать работу. Если вам нужно создавать эффективные приложения реального времени на работе, WebSocket будет лучшим выбором.