Skip to content

Привязка UDP-сокета (Bun.udpSocket())

Для создания нового (привязанного) UDP-сокета:

ts
const socket = await Bun.udpSocket({});
console.log(socket.port); // назначено операционной системой

Укажите порт:

ts
const socket = await Bun.udpSocket({
  port: 41234, 
});

console.log(socket.port); // 41234

Отправка датаграммы

Укажите данные для отправки а также порт назначения и адрес.

ts
socket.send("Hello, world!", 41234, "127.0.0.1");

Обратите внимание что адрес должен быть действительным IP-адресом — send не выполняет DNS-разрешение так как предназначен для операций с низкой задержкой.

Получение датаграмм

При создании сокета добавьте обратный вызов для указания того что должно быть сделано при получении пакетов:

ts
const server = await Bun.udpSocket({
  socket: {
    data(socket, buf, port, addr) {
      console.log(`сообщение от ${addr}:${port}:`);
      console.log(buf.toString());
    },
  },
});

const client = await Bun.udpSocket({});
client.send("Hello!", server.port, "127.0.0.1");

Соединения

Хотя UDP не имеет понятия соединения многие UDP-коммуникации (особенно в качестве клиента) включают только одного пира. В таких случаях может быть полезно подключить сокет к этому пиру что указывает на какой адрес отправляются все пакеты и ограничивает входящие пакеты только этим пиром.

ts
const server = await Bun.udpSocket({
  socket: {
    data(socket, buf, port, addr) {
      console.log(`сообщение от ${addr}:${port}:`);
      console.log(buf.toString());
    },
  },
});

const client = await Bun.udpSocket({
  connect: {
    port: server.port,
    hostname: "127.0.0.1",
  },
});

client.send("Hello");

Поскольку соединения реализуются на уровне операционной системы вы также можете наблюдать преимущества производительности.

Отправка множества пакетов одновременно с помощью sendMany()

Если вы хотите отправить большой объём пакетов одновременно может иметь смысл объединить их все вместе чтобы избежать накладных расходов на системный вызов для каждого. Это становится возможным благодаря API sendMany():

Для неподключенного сокета sendMany принимает массив в качестве единственного аргумента. Каждый набор из трёх элементов массива описывает пакет: Первый элемент — данные для отправки второй — целевой порт и последний — целевой адрес.

ts
const socket = await Bun.udpSocket({});

// отправляет 'Hello' на 127.0.0.1:41234 и 'foo' на 1.1.1.1:53 за одну операцию
socket.sendMany(["Hello", 41234, "127.0.0.1", "foo", 53, "1.1.1.1"]);

С подключенным сокетом sendMany просто принимает массив где каждый элемент представляет данные для отправки пиру.

ts
const socket = await Bun.udpSocket({
  connect: {
    port: 41234,
    hostname: "localhost",
  },
});

socket.sendMany(["foo", "bar", "baz"]);

sendMany возвращает количество пакетов которые были успешно отправлены. Как и send sendMany принимает только действительные IP-адреса в качестве назначений так как не выполняет DNS-разрешение.

Обработка обратного давления

Может случиться так что пакет который вы отправляете не помещается в буфер пакетов операционной системы. Вы можете обнаружить что это произошло когда:

  • send возвращает false
  • sendMany возвращает число меньше чем количество пакетов которые вы указали. В этом случае обработчик сокета drain будет вызван как только сокет снова станет доступен для записи:
ts
const socket = await Bun.udpSocket({
  socket: {
    drain(socket) {
      // продолжить отправку данных
    },
  },
});

Bun от www.bunjs.com.cn