Spec-Zone.ru › Node.js 10 LTS

UDP/Сокеты дейтаграмм

Устойчивость: 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[src]

Добавлена в: 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])[src]

Добавлена в: 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()[src]

Добавлена в: v0.1.99
  • Возвращает: <Объект>

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

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

Добавлена в: 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])[src]

Добавлена в: 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])[src]

Добавлена в: v0.1.99
  • callback <Функция> Вызывается, когда сокет закрыт.

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

socket.dropMembership(multicastAddress[, multicastInterface])[src]

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

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

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

socket.getRecvBufferSize()[src]

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

socket.getSendBufferSize()[src]

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

socket.ref()[src]

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

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

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

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

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

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

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

v8.0.0

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

v6.0.0

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

v5.7.0

Параметр msg теперь может быть массивом. Также параметры offset и length теперь необязательны.

v0.1.99

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

  • msg <Буфер> | <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 (Maximum Transmission Unit) и размера поля Payload Length.

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

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

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

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

socket.setBroadcast(flag)[src]

Добавлен в: v0.6.9
  • flag <булево>

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

socket.setMulticastInterface(multicastInterface)[src]

Добавлен в: 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');
});

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

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

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

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

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

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

socket.setMulticastLoopback(flag)[src]

Added in: v0.3.8
  • flag <boolean>

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

socket.setMulticastTTL(ttl)[src]

Added in: v0.3.8
  • ttl <integer>

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

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

socket.setRecvBufferSize(size)[src]

Added in: v8.7.0
  • size <integer>

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

socket.setSendBufferSize(size)[src]

Added in: v8.7.0
  • size <integer>

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

socket.setTTL(ttl)[src]

Added in: v0.1.101
  • ttl <integer>

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

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

socket.unref()[src]

Added in: 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])[src]

История
Версия Изменения
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() укажет сокету начать прослушивание сообщений datagram. Когда address и port не переданы в socket.bind(), метод привяжет сокет к адресу «все интерфейсы» на случайном порту (он делает правильно и для сокетов udp4 и udp6). Привязанный адрес и порт можно получить, используя socket.address().address и socket.address().port.

dgram.createSocket(type[, callback])[src]

Added in: 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-v10.x/docs/api/dgram.html

Spec-Zone.ru

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