Что такое UDP и как с ним работать в Node.js?

Ответ

UDP (User Datagram Protocol) — это протокол транспортного уровня, альтернативный TCP. Его главное отличие — отсутствие установки соединения и гарантий доставки. Он отправляет независимые пакеты данных (датаграммы), что делает его быстрее, но менее надежным.

Характеристики UDP:

  • Без установки соединения: Нет «рукопожатия» (handshake).
  • Ненадежный: Пакеты могут быть потеряны, продублированы или прийти в неправильном порядке.
  • Не гарантирует целостность: Нет встроенного подтверждения получения.
  • Быстрый: Минимальные накладные расходы на заголовки и управление.

Когда использовать UDP в Node.js?

  • Стриминг (видео/аудио): Потеря нескольких пакетов менее критична, чем задержка.
  • DNS-запросы: Быстрые запросы, где если ответ потерян, клиент просто повторит его.
  • Многопользовательские онлайн-игры: Важна минимальная задержка (low latency).
  • Широковещательные (broadcast) и multicast-рассылки.

Работа с UDP в Node.js (модуль dgram):

const dgram = require('dgram');

// Создание UDP-сокета
const server = dgram.createSocket('udp4'); // 'udp4' для IPv4, 'udp6' для IPv6

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

server.on('message', (msg, rinfo) => {
  // rinfo содержит адрес и порт отправителя
  console.log(`Server received: "${msg}" from ${rinfo.address}:${rinfo.port}`);
  // Можно отправить ответ обратно
  server.send(`Echo: ${msg}`, rinfo.port, rinfo.address);
});

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

// Привязка сервера к порту 41234
server.bind(41234);

// --- Клиентская часть ---
const client = dgram.createSocket('udp4');
const message = Buffer.from('Hello UDP Server!');

client.send(message, 41234, 'localhost', (err) => {
  if (err) {
    client.close();
    throw err;
  }
  console.log('Message sent');
});

client.on('message', (msg) => {
  console.log(`Client got reply: ${msg}`);
  client.close();
});

Важно: Для задач, где важна надежная доставка и порядок данных (веб-API, загрузка файлов, электронная почта), всегда используйте TCP (например, через модуль net или HTTP/HTTPS).

Ответ 18+ 🔞

Ну, вот смотри, история про UDP — это как будто ты пытаешься орать что-то через окно соседу в соседний дом. Ты просто крикнул и похуй, дошло или нет. Никаких «приём, как слышно?», никаких «повтори, я не расслышал». Крикнул и забыл. Это и есть UDP, ёпта.

Что это за зверь такой?

  • Без установки связи: Никаких этих рукопожатий, как у его занудного брата TCP. Просто взял и отправил пакет в никуда.
  • Ненадёжный как обещание алкаша: Пакеты могут потеряться, прийти два раза или вообще вперемешку. Гарантий — ноль ебать.
  • Быстрый, потому что тупой: Заголовок маленький, мозгов не тратит, летит как угорелый. Идеально, когда скорость важнее, чем чтобы всё до последней запятой дошло.

Где это говно вообще нужно?

  • Стриминг видео или музыки: Потерял пару пакетов — ну и хуй с ним, глаз не заметит. А вот если начнёт буфер из-за задержек строить — это уже пиздец, все уйдут.
  • DNS-запросы: Ты спрашиваешь у сервера «какой там IP у гугла?». Если ответ потерялся — да похуй, спросишь ещё раз через секунду.
  • Онлайн-игрули: Тут важна скорость, чтобы твой выстрел летел мгновенно. Лучше потерять пару пакетов о погоде на карте, чем начать лагать.
  • Массовые рассылки: Когда нужно орать одно и то же всем подряд в сети.

Как с этим работать в Node.js (модуль dgram):

Смотри, вот тебе живой пример. Сервер, который слушает и орет в ответ.

const dgram = require('dgram');

// Создаём сокет. Типа открыли окно.
const server = dgram.createSocket('udp4'); // 'udp4' — это для обычного интернета, IPv4

// Если всё пошло по пизде — ловим ошибку.
server.on('error', (err) => {
  console.error(`Server error:n${err.stack}`);
  server.close();
});

// А вот это главное — что делать, когда нам что-то прилетело в окно.
server.on('message', (msg, rinfo) => {
  // rinfo — это инфо о том, кто орал. Его адрес и порт.
  console.log(`Server received: "${msg}" from ${rinfo.address}:${rinfo.port}`);
  // Тут же можно и ответить! Крикнул обратно в то же окно.
  server.send(`Echo: ${msg}`, rinfo.port, rinfo.address);
});

// Когда сервер привязался к порту и готов орать.
server.on('listening', () => {
  const address = server.address();
  console.log(`UDP Server listening on ${address.address}:${address.port}`);
});

// Говорим: слушай порт 41234.
server.bind(41234);

// --- А это клиент, который первый начинает орать ---
const client = dgram.createSocket('udp4');
const message = Buffer.from('Hello UDP Server!'); // Сообщение в буфере

// Отправляем! На порт 41234, на локалхост.
client.send(message, 41234, 'localhost', (err) => {
  if (err) {
    client.close();
    throw err;
  }
  console.log('Message sent');
});

// Ждём, не ответит ли кто.
client.on('message', (msg) => {
  console.log(`Client got reply: ${msg}`);
  client.close(); // Получили ответ и закрыли своё окно.
});

Важный момент, блядь: Если тебе нужно, чтобы всё дошло точно, в порядке и без потерь — это не сюда. Для веба, API, отправки файлов — там нужен TCP, с его рукопожатиями и гарантиями. А UDP — это когда «крикнул и надеюсь».