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