Spec-Zone.ru › Node.js 8 LTS

UDP/Датagram-сокеты

Уровень стабильности: 2 - Стабильно

Модуль dgram предоставляет реализацию UDP-сокетров для работы с дейтаграммами.

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234);
// server listening 0.0.0.0:41234

Класс: dgram.Socket

Добавлен в: v0.1.99

Объект dgram.Socket является объектом EventEmitter, который инкапсулирует функциональность дейтаграмм.

Новые экземпляры dgram.Socket создаются с помощью dgram.createSocket(). Ключевое слово new не используется для создания экземпляров dgram.Socket.

Событие: 'close'

Добавлен в: v0.1.99

Событие 'close' генерируется после закрытия сокета с помощью close(). После его срабатывания новые события 'message' на этом сокете не будут генерироваться.

Событие: 'error'

Добавлен в: v0.1.99
  • exception <Ошибка>

Событие 'error' генерируется всякий раз, когда происходит ошибка. Обработчик событий получает один объект Error.

Событие: 'listening'

Добавлен в: v0.1.99

Событие 'listening' генерируется всякий раз, когда сокет начинает прослушивать сообщения дейтаграмм. Это происходит сразу после создания UDP-сокетов.

Событие: 'message'

Добавлен в: v0.1.99

Событие 'message' генерируется, когда на сокете появляется новое сообщение дейтаграммы. Обработчик событий получает два аргумента: msg и rinfo.

  • msg <Буфер> Сообщение.
  • rinfo <Объект> Информация о удалённом адресе.
    • address <Строка> Адрес отправителя.
    • family <Строка> Семейство адресов ('IPv4' или 'IPv6').
    • port <Число> Порт отправителя.
    • size <Число> Размер сообщения.

socket.addMembership(multicastAddress[, multicastInterface])

Добавлен в: v0.6.9
  • multicastAddress <Строка>
  • multicastInterface <Строка>

Указывает ядру присоединиться к группе мультивещания по заданному multicastAddress и multicastInterface используя опцию сокета IP_ADD_MEMBERSHIP. Если аргумент multicastInterface не указан, операционная система выберет один интерфейс и добавит к нему членство. Чтобы добавить членство ко всем доступным интерфейсам, вызовите addMembership несколько раз, по одному на каждый интерфейс.

При совместном использовании UDP-сокета несколькими cluster рабочими процессами, функция socket.addMembership() должна быть вызвана только один раз, иначе произойдёт ошибка EADDRINUSE.

const cluster = require('cluster');
const dgram = require('dgram');
if (cluster.isMaster) {
  cluster.fork(); // Works ok.
  cluster.fork(); // Fails with EADDRINUSE.
} else {
  const s = dgram.createSocket('udp4');
  s.bind(1234, () => {
    s.addMembership('224.0.0.114');
  });
}

socket.address()

Добавлен в: v0.1.99

Возвращает объект, содержащий информацию об адресе сокета. Для UDP-сокетов этот объект будет содержать address, family и port свойства.

socket.bind([port][, address][, callback])

Добавлен в: v0.1.99
  • port <Целое число>
  • address <Строка>
  • callback <Функция> без параметров. Вызывается по завершении привязки.

Для UDP-сокетов заставляет dgram.Socket прослушивать сообщения дейтаграмм по указанному port и необязательному address. Если port не указан или равен 0, операционная система попытается привязаться к случайному порту. Если address не указан, операционная система попытается прослушивать все адреса. После завершения привязки генерируется событие 'listening' и, если задана, вызывается функция callback.

Обратите внимание, что указание слушателя события 'listening' и передача callback методу socket.bind() не наносит вреда, но не очень полезно.

Сокет дейтаграмм, который привязан, удерживает процесс Node.js работающим для получения сообщений дейтаграмм.

Если привязка не удалась, генерируется событие 'error' . В редких случаях (например, при попытке привязки к закрытому сокету) может быть выброшено исключение Error.

Пример UDP-сервера, слушающего на порту 41234:

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234);
// server listening 0.0.0.0:41234

socket.bind(options[, callback])

Добавлен в: v0.11.14
  • options <Объект> Требуется. Поддерживает следующие свойства:
    • port <Целое число>
    • address <Строка>
    • exclusive <Булево>
  • callback <Функция>

Для UDP-сокетов заставляет dgram.Socket прослушивать сообщения дейтаграмм по указанному port и необязательному address , которые передаются как свойства объекта options в качестве первого аргумента. Если port не указан или равен 0, операционная система попытается привязаться к случайному порту. Если address не указан, операционная система попытается прослушивать все адреса. После завершения привязки генерируется событие 'listening' и, если задана, вызывается функция callback.

Обратите внимание, что указание слушателя события 'listening' и передача callback методу socket.bind() не наносит вреда, но не очень полезно.

Объект options может содержать дополнительное свойство exclusive, которое используется при работе с объектами dgram.Socket с модулем cluster. Если exclusive установлено в false (по умолчанию), рабочие процессы кластера будут использовать тот же базовый дескриптор сокета, что позволит совместно обрабатывать подключения. Однако, если exclusive равно true, дескриптор не делится, и попытка совместно использовать порт приводит к ошибке.

Сокет дейтаграмм, который привязан, удерживает процесс Node.js работающим для получения сообщений дейтаграмм.

Если привязка не удалась, генерируется событие 'error' . В редких случаях (например, при попытке привязки к закрытому сокету) может быть выброшено исключение Error.

Ниже показан пример сокета, слушающего на исключительном порту.

socket.bind({
  address: 'localhost',
  port: 8000,
  exclusive: true
});

socket.close([callback])

Добавлен в: v0.1.99

Закрыть базовый сокет и прекратить прослушивание данных на нём. Если указан обработчик, он добавляется как слушатель события 'close'.

socket.dropMembership(multicastAddress[, multicastInterface])

Добавлен в: v0.6.9
  • multicastAddress <Строка>
  • multicastInterface <Строка>

Инструктирует ядро покинуть группу мультивещания по multicastAddress используя опцию сокета IP_DROP_MEMBERSHIP. Этот метод автоматически вызывается ядром при закрытии сокета или завершении процесса, поэтому большинству приложений никогда не придётся его вызывать.

Если multicastInterface не указан, операционная система попытается покинуть членство на всех доступных интерфейсах.

socket.getRecvBufferSize()

Добавлен в: v8.7.0
  • Возвращает: <Число> размер буфера приема сокета в байтах.

socket.getSendBufferSize()

Добавлен в: v8.7.0
  • Возвращает: <Число> размер буфера отправки сокета в байтах.

socket.ref()

Добавлен в: v0.9.1

По умолчанию, привязка сокета приводит к блокировке процесса Node.js до тех пор, пока сокет открыт. Метод socket.unref() может быть использован для исключения сокета из подсчёта ссылок, который удерживает активным процесс Node.js. Метод socket.ref() добавляет сокет обратно в подсчёт ссылок и восстанавливает стандартное поведение.

Вызов socket.ref() несколько раз не приведёт к дополнительным эффектам.

Метод socket.ref() возвращает ссылку на сокет, позволяя выполнять цепочку вызовов.

socket.send(msg, [offset, length,] port [, address] [, callback])

История
Версия Изменения
v8.0.0

Параметр msg теперь может быть типа Uint8Array.

v8.0.0

Параметр address теперь всегда является необязательным.

v6.0.0

При успехе, callback теперь будет вызван с аргументом error типа null, а не 0.

v5.7.0

Параметр msg теперь может быть массивом. Кроме того, параметры offset и length теперь являются необязательными.

v0.1.99

Добавлен в: v0.1.99

  • msg <Buffer> | <Uint8Array> | <строка> | <массив> Сообщение для отправки.
  • offset <число> Целое число. Смещение в буфере, где начинается сообщение.
  • length <число> Целое число. Количество байтов в сообщении.
  • port <число> Целое число. Порт назначения.
  • address <строка> Имя хоста или IP-адрес назначения.
  • callback <функция> Вызывается при отправке сообщения.

Отправляет дейтаграмму по сокету. Необходимо указать адрес и порт назначения port и address.

Аргумент msg содержит сообщение для отправки. В зависимости от его типа, может применяться разное поведение. Если msg является Buffer или Uint8Array, параметры offset и length определяют смещение в Buffer и количество байтов в сообщении соответственно. Если msg является String, оно автоматически преобразуется в Buffer с кодировкой 'utf8'. При сообщениях, содержащих многобайтовые символы, offset и length вычисляются относительно длины в байтах, а не позиции символа. Если msg является массивом, offset и length не должны быть указаны.

Аргумент address является строкой. Если значение address — имя хоста, используется DNS для разрешения адреса хоста. Если address не указано или имеет ложное значение, используется '127.0.0.1' (для сокетов udp4) или '::1' (для сокетов udp6) по умолчанию.

Если сокет не был предварительно привязан с помощью вызова bind, ему присваивается случайный номер порта и он привязывается к адресу «все интерфейсы» ('0.0.0.0' для сокетов udp4, '::0' для сокетов udp6).

В качестве необязательной функции callback можно указать способ обработки ошибок DNS или определения момента, когда можно безопасно повторно использовать объект buf. Обратите внимание, что поиск по DNS задерживает время отправки как минимум на один такт цикла событий Node.js.

Единственный способ точно узнать, что дейтаграмма была отправлена, — использовать callback. Если произошла ошибка, и задана callback, ошибка будет передана в качестве первого аргумента в callback. Если callback не указана, ошибка передается как событие 'error' объекта socket.

Смещение и длина являются необязательными, но обязательно должны быть установлены, если они используются. Они поддерживаются только в том случае, если первый аргумент является Buffer или Uint8Array.

Пример отправки UDP-пакета на порт на localhost;

const dgram = require('dgram');
const message = Buffer.from('Some bytes');
const client = dgram.createSocket('udp4');
client.send(message, 41234, 'localhost', (err) => {
  client.close();
});

Пример отправки UDP-пакета, состоящего из нескольких буферов, на порт на 127.0.0.1;

const dgram = require('dgram');
const buf1 = Buffer.from('Some ');
const buf2 = Buffer.from('bytes');
const client = dgram.createSocket('udp4');
client.send([buf1, buf2], 41234, (err) => {
  client.close();
});

Отправка нескольких буферов может быть быстрее или медленнее в зависимости от приложения и операционной системы. Важно выполнить бенчмаркинг, чтобы определить оптимальную стратегию в каждом конкретном случае. В целом, однако, отправка нескольких буферов быстрее.

Примечание по размеру UDP-дейтаграммы

Максимальный размер UDP-дейтаграммы зависит от MTU (Максимального размера блока передачи) и от размера поля Payload Length.

  • Поле Payload Length имеет ширину 16 bits, что означает, что обычная нагрузка превысит 64К байтов включая заголовок интернета и данные (65 507 байт = 65 535 − 8 байт UDP-заголовка − 20 байт IP-заголовка); это в общем случае верно для петель обратной связи, но такие длинные сообщения дейтаграмм непрактичны для большинства хостов и сетей.

  • MTU — это максимальный размер, который поддерживает конкретная технология канального уровня для сообщений дейтаграмм. Для любого канала IPv4 устанавливает минимальный MTU в 68 октетов, а рекомендуемый MTU для IPv4 — 576 (обычно рекомендуется как MTU для приложений типа dial-up), независимо от того, приходят ли они целиком или фрагментами.

    Для IPv6, минимальный MTU составляет 1280 октетов, однако, минимальный размер буфера повторной сборки фрагментов составляет 1500 октетов. Значение 68 октетов очень мало, так как большинство современных технологий канального уровня, таких как Ethernet, имеют минимальный MTU из 1500.

Невозможно заранее знать MTU каждого канала, по которому может проходить пакет. Отправка дейтаграммы, превышающей размер буфера получателя MTU, не сработает, поскольку пакет будет молча отброшен без уведомления источника о том, что данные не достигли адресата.

socket.setBroadcast(flag)

Добавлен в: v0.6.9
  • flag <логическое значение>

Устанавливает или сбрасывает параметр сокета SO_BROADCAST. При установке в true UDP-пакеты могут отправляться на адрес широковещательной рассылки локального интерфейса.

socket.setMulticastInterface(multicastInterface)

Добавлен в: v8.6.0
  • multicastInterface <строка>

Примечание: Все ссылки на область действия в этом разделе относятся к индексам зоны IPv6, которые определены в RFC 4007. В строчном формате IP с индексом области действия записывается как 'IP%scope' где область действия — имя или номер интерфейса.

Устанавливает значение по умолчанию исходящего интерфейса для мультиадресной рассылки сокета на выбранный интерфейс или на выбор системного интерфейса. multicastInterface должен быть корректной строковой записью IP-адреса из семейства сокета.

Для IPv4-сокетов это должен быть IP-адрес, настроенный для нужного физического интерфейса. Все пакеты, отправляемые в мультиадресную рассылку по сокету, будут отправляться по интерфейсу, определенному последним успешным использованием этого вызова.

Для IPv6-сокетов multicastInterface должен содержать область действия, чтобы указать интерфейс, как в примерах ниже. В IPv6 отдельные send вызовы также могут использовать явный индекс области в адресах, поэтому только пакеты, отправленные на мультиадресной адрес без явного указания области, влияют на последнее успешное использование этого вызова.

Примеры: IPv6 исходящий интерфейс для мультиадресной рассылки

На большинстве систем, где формат области действия использует имя интерфейса:

const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%eth1');
});

На Windows, где формат области действия использует номер интерфейса:

const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%2');
});

Пример: IPv4 исходящий интерфейс для мультиадресной рассылки

Все системы используют IP-адрес хоста на желаемом физическом интерфейсе:

const socket = dgram.createSocket('udp4');

socket.bind(1234, () => {
  socket.setMulticastInterface('10.0.0.2');
});

Результаты вызова

Вызов сокета, который не готов к отправке или больше не открыт, может вызвать исключение Не работает Error.

Если multicastInterface не может быть обработано как IP-адрес, то выбрасывается исключение EINVAL System Error.

В IPv4, если multicastInterface — допустимый адрес, но не соответствует ни одному интерфейсу, или если адрес не соответствует семейству, выбрасывается исключение System Error, например, EADDRNOTAVAIL или EPROTONOSUP.

В IPv6 большинство ошибок при указании или пропуске области действия приведут к тому, что сокет будет продолжать использовать (или возвращаться к) выбору системного интерфейса по умолчанию.

Адрес ANY семейства адресов сокета (IPv4 '0.0.0.0' или IPv6 '::') может использоваться для возврата управления по умолчанию исходящим интерфейсом сокетов системе для будущих пакетов мультиадресной рассылки.

socket.setMulticastLoopback(flag)

Добавлена в: v0.3.8
  • flag <boolean>

Устанавливает или очищает параметр сокета IP_MULTICAST_LOOP. Если установлен в true, пакеты multicast также будут приниматься на локальном интерфейсе.

socket.setMulticastTTL(ttl)

Добавлена в: v0.3.8
  • ttl <number> Целое число.

Устанавливает параметр сокета IP_MULTICAST_TTL. Хотя TTL обычно означает «Время жизни», в данном контексте он определяет количество IP-пересадок, которые пакет разрешено пройти, в частности, для мультимедийного трафика. Каждый маршрутизатор или шлюз, пересылающий пакет, уменьшает TTL. Если TTL уменьшается до 0 маршрутизатором, пакет не будет пересылаться.

Передаваемое аргумент в socket.setMulticastTTL() число пересадок от 0 до 255. По умолчанию на большинстве систем 1, но может отличаться.

socket.setRecvBufferSize(size)

Добавлена в: v8.7.0
  • size <number> Целое число

Устанавливает параметр сокета SO_RCVBUF. Устанавливает максимальный буфер приема сокета в байтах.

socket.setSendBufferSize(size)

Добавлена в: v8.7.0
  • size <number> Целое число

Устанавливает параметр сокета SO_SNDBUF. Устанавливает максимальный буфер отправки сокета в байтах.

socket.setTTL(ttl)

Добавлена в: v0.1.101
  • ttl <number> Целое число.

Устанавливает параметр сокета IP_TTL. Хотя TTL обычно означает «Время жизни», в данном контексте он определяет количество IP-пересадок, которые пакет разрешено пройти. Каждый маршрутизатор или шлюз, пересылающий пакет, уменьшает TTL. Если TTL уменьшается до 0 маршрутизатором, пакет не будет пересылаться. Изменение значений TTL обычно выполняется для сетевых зондирований или при мультивещании.

Аргумент для socket.setTTL() — число пересадок от 1 до 255. По умолчанию на большинстве систем 64, но может отличаться.

socket.unref()

Добавлена в: v0.9.1

По умолчанию привязка сокета заблокирует процесс Node.js до тех пор, пока сокет не будет закрыт. Метод socket.unref() может использоваться для исключения сокета из подсчета ссылок, который поддерживает активность процесса Node.js, позволяя процессу выйти, даже если сокет всё ещё прослушивает.

Вызов socket.unref() несколько раз не повлияет.

Метод socket.unref() возвращает ссылку на сокет, поэтому вызовы могут быть объединены.

Изменение асинхронного socket.bind() поведения

Начиная с Node.js v0.10, dgram.Socket#bind() изменился на асинхронную модель выполнения. Код старого образца, предполагающий синхронное поведение, как в приведённом примере:

const s = dgram.createSocket('udp4');
s.bind(1234);
s.addMembership('224.0.0.114');

Должен быть изменён, чтобы передать функцию обратного вызова в dgram.Socket#bind() функцию:

const s = dgram.createSocket('udp4');
s.bind(1234, () => {
  s.addMembership('224.0.0.114');
});

dgram функции модуля

dgram.createSocket(options[, callback])

История
Версия Изменения
v8.7.0

Теперь поддерживаются параметры recvBufferSize и sendBufferSize.

v8.6.0

Теперь поддерживается параметр lookup.

v0.11.13

Добавлена в: v0.11.13

  • options <Object> Доступные параметры:
    • type <string> Семейство сокета. Должно быть либо 'udp4' или 'udp6'. Требуется.
    • reuseAddr <boolean> Когда true socket.bind() будет повторно использовать адрес, даже если другой процесс уже привязал сокет к нему. По умолчанию: false.
    • recvBufferSize <number> - Устанавливает значение сокета SO_RCVBUF.
    • sendBufferSize <number> - Устанавливает значение сокета SO_SNDBUF.
    • lookup <Function> Пользовательская функция поиска. По умолчанию: dns.lookup().
  • callback <Function> Прикреплён как обработчик событий 'message'. Необязательно.
  • Возвращает: <dgram.Socket>

Создаёт объект dgram.Socket. После создания сокета, вызов socket.bind() укажет сокету начать прослушивание сообщений датаграмм. Когда address и port не передаются в socket.bind(), метод привяжет сокет к адресу «всех интерфейсов» на случайном порту (он выполняет правильную работу как для udp4 так и для udp6 сокетов). Связанный адрес и порт можно получить с помощью socket.address().address и socket.address().port.

dgram.createSocket(type[, callback])

Добавлена в: v0.1.99
  • type <string> - Либо 'udp4', либо 'udp6'.
  • callback <Function> - Прикреплён как обработчик событий 'message'.
  • Возвращает: <dgram.Socket>

Создаёт объект dgram.Socket указанного типа type. Аргумент type может быть либо udp4 или udp6. Необязательная функция callback может быть передана, которая добавляется как обработчик событий 'message'.

После создания сокета, вызов socket.bind() укажет сокету начать прослушивание сообщений датаграмм. Когда address и port не передаются в socket.bind(), метод привяжет сокет к адресу «всех интерфейсов» на случайном порту (он выполняет правильную работу как для udp4 так и для udp6 сокетов). Связанный адрес и порт можно получить с помощью socket.address().address и socket.address().port.

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v8.x/docs/api/dgram.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API