WebSocket-клиент
WebSocket-клиент
Заголовок раздела «WebSocket-клиент»WebSocket-клиент для двунаправленной связи с серверами в реальном времени.
Загрузка
Заголовок раздела «Загрузка»local websocket = require("websocket")Подключение
Заголовок раздела «Подключение»Базовое подключение
Заголовок раздела «Базовое подключение»local client, err = websocket.connect("wss://api.example.com/ws")if err then return nil, errendС опциями
Заголовок раздела «С опциями»local client, err = websocket.connect("wss://api.example.com/ws", { headers = { ["Authorization"] = "Bearer " .. token }, protocols = {"graphql-ws"}, dial_timeout = "10s", read_timeout = "30s", compression = websocket.COMPRESSION.CONTEXT_TAKEOVER})| Параметр | Тип | Описание |
|---|---|---|
url | string | WebSocket URL (ws:// или wss://) |
options | table | Опции подключения (опционально) |
Возвращает: Client, error
Опции подключения
Заголовок раздела «Опции подключения»| Опция | Тип | Описание |
|---|---|---|
headers | table | HTTP-заголовки для рукопожатия |
protocols | table | WebSocket-подпротоколы |
dial_timeout | number/string | Таймаут подключения (мс или “5s”) |
read_timeout | number/string | Таймаут чтения |
write_timeout | number/string | Таймаут записи |
compression | number | Режим сжатия (см. Константы) |
compression_threshold | number | Мин. размер для сжатия (0-100MB) |
read_limit | number | Макс. размер сообщения (0-128MB) |
channel_capacity | number | Буфер канала приёма (1-10000) |
Формат таймаута: Числа в миллисекундах, строки в формате Go duration (“5s”, “1m”).
Отправка сообщений
Заголовок раздела «Отправка сообщений»Текстовые сообщения
Заголовок раздела «Текстовые сообщения»local ok, err = client:send("Hello, Server!")if err then return nil, errend
-- Отправка JSONclient:send(json.encode({ type = "subscribe", channel = "orders"}))Бинарные сообщения
Заголовок раздела «Бинарные сообщения»client:send(binary_data, websocket.BINARY)| Параметр | Тип | Описание |
|---|---|---|
data | string | Содержимое сообщения |
type | number | websocket.TEXT (1) или websocket.BINARY (2) |
Возвращает: boolean, error
client:ping()Возвращает: boolean, error
Приём сообщений
Заголовок раздела «Приём сообщений»Метод channel() возвращает канал для приёма сообщений. receive() является алиасом для channel(). Работает с channel.select для мультиплексирования.
Базовый приём
Заголовок раздела «Базовый приём»local ch = client:channel()
local msg, ok = ch:receive()if ok then print("Type:", msg.type) -- "text" или "binary" print("Data:", msg.data)endЦикл сообщений
Заголовок раздела «Цикл сообщений»local ch = client:channel()
while true do local msg, ok = ch:receive() if not ok then break -- Соединение закрыто end
if msg.type == "text" then local data = json.decode(msg.data) handle_message(data) endendС select
Заголовок раздела «С select»local ch = client:channel()local timeout = time.after("30s")
while true do local r = channel.select { ch:case_receive(), timeout:case_receive() }
if r.channel == timeout then client:ping() -- Keep-alive timeout = time.after("30s") else local data = json.decode(r.value.data) process(data) endendОбъект сообщения
Заголовок раздела «Объект сообщения»| Поле | Тип | Описание |
|---|---|---|
type | string | "text" или "binary" |
data | string? | Содержимое сообщения (nil для неизвестных типов нагрузки) |
Закрытие соединения
Заголовок раздела «Закрытие соединения»-- Нормальное закрытие (код 1000)client:close()
-- С кодом и причинойclient:close(websocket.CLOSE_CODES.NORMAL, "Session ended")
-- Закрытие с ошибкойclient:close(websocket.CLOSE_CODES.INTERNAL_ERROR, "Processing failed")| Параметр | Тип | Описание |
|---|---|---|
code | number | Код закрытия (1000-4999), по умолчанию 1000 |
reason | string | Причина закрытия (опционально) |
Возвращает: boolean, error
Константы
Заголовок раздела «Константы»Типы сообщений
Заголовок раздела «Типы сообщений»-- Числовые (для отправки)websocket.TEXT -- 1websocket.BINARY -- 2
-- Строковые (поле type полученного сообщения)websocket.TYPE_TEXT -- "text"websocket.TYPE_BINARY -- "binary"websocket.TYPE_PING -- "ping"websocket.TYPE_PONG -- "pong"websocket.TYPE_CLOSE -- "close"Режимы сжатия
Заголовок раздела «Режимы сжатия»websocket.COMPRESSION.DISABLED -- 0 (без сжатия)websocket.COMPRESSION.CONTEXT_TAKEOVER -- 1 (скользящее окно)websocket.COMPRESSION.NO_CONTEXT -- 2 (по-сообщенийно)Коды закрытия
Заголовок раздела «Коды закрытия»| Константа | Код | Описание |
|---|---|---|
NORMAL | 1000 | Нормальное закрытие |
GOING_AWAY | 1001 | Сервер завершает работу |
PROTOCOL_ERROR | 1002 | Ошибка протокола |
UNSUPPORTED_DATA | 1003 | Неподдерживаемый тип данных |
RESERVED | 1004 | Зарезервировано |
NO_STATUS | 1005 | Статус не получен |
ABNORMAL_CLOSURE | 1006 | Соединение потеряно |
INVALID_PAYLOAD | 1007 | Некорректные данные фрейма |
POLICY_VIOLATION | 1008 | Нарушение политики |
MESSAGE_TOO_BIG | 1009 | Сообщение слишком большое |
MANDATORY_EXTENSION | 1010 | Требуемое расширение не согласовано |
INTERNAL_ERROR | 1011 | Ошибка сервера |
SERVICE_RESTART | 1012 | Сервер перезапускается |
TRY_AGAIN_LATER | 1013 | Сервер перегружен |
BAD_GATEWAY | 1014 | Ошибка шлюза |
TLS_HANDSHAKE | 1015 | Ошибка TLS handshake |
client:close(websocket.CLOSE_CODES.NORMAL, "Done")Примеры
Заголовок раздела «Примеры»Чат в реальном времени
Заголовок раздела «Чат в реальном времени»local function connect_chat(room_id, on_message) local client, err = websocket.connect("wss://chat.example.com/ws", { headers = {["Authorization"] = "Bearer " .. token} }) if err then return nil, err end
-- Вход в комнату client:send(json.encode({ type = "join", room = room_id }))
-- Цикл сообщений local ch = client:channel() while true do local msg, ok = ch:receive() if not ok then break end
local data = json.decode(msg.data) on_message(data) end
client:close()endПоток цен с keep-alive
Заголовок раздела «Поток цен с keep-alive»local client = websocket.connect("wss://stream.example.com/prices")
client:send(json.encode({ action = "subscribe", symbols = {"BTC-USD", "ETH-USD"}}))
local ch = client:channel()local heartbeat = time.after("30s")
while true do local r = channel.select { ch:case_receive(), heartbeat:case_receive() }
if r.channel == heartbeat then client:ping() heartbeat = time.after("30s") elseif not r.ok then break -- Соединение закрыто else local price = json.decode(r.value.data) update_price(price.symbol, price.value) endend
client:close()Разрешения
Заголовок раздела «Разрешения»WebSocket-соединения подчиняются вычислению политики безопасности.
Действия безопасности
Заголовок раздела «Действия безопасности»| Действие | Ресурс | Описание |
|---|---|---|
websocket.connect | - | Разрешить/запретить WebSocket-соединения |
websocket.connect.url | URL | Разрешить/запретить соединения с конкретными URL |
См. Модель безопасности для настройки политик.
| Условие | Kind | Повторяемо |
|---|---|---|
| Соединения отключены | errors.PERMISSION_DENIED | нет |
| URL не разрешён | errors.PERMISSION_DENIED | нет |
| Нет контекста | errors.INTERNAL | нет |
| Ошибка подключения | errors.INTERNAL | да |
| Некорректный ID соединения | errors.INTERNAL | нет |
local client, err = websocket.connect(url)if err then if errors.is(err, errors.PERMISSION_DENIED) then print("Access denied:", err:message()) elseif err:retryable() then print("Temporary error:", err:message()) end return nil, errendСм. Обработка ошибок для работы с ошибками.