UDP
Use Bun's UDP API to implement services with advanced real-time requirements, such as voice chat.
Bind a UDP socket (Bun.udpSocket())
To create a new (bound) UDP socket:
const socket = await Bun.udpSocket({});
console.log(socket.port); // assigned by the operating systemSpecify a port:
const socket = await Bun.udpSocket({
port: 41234,
});
console.log(socket.port); // 41234Send a datagram
Specify the data to send, the destination port, and the destination address.
socket.send("Hello, world!", 41234, "127.0.0.1");The address must be a valid IP address. send does not perform DNS
resolution, as it is intended for low-latency operations.
Receive datagrams
When creating your socket, add a data callback to handle incoming packets:
const server = await Bun.udpSocket({
socket: {
data(socket, buf, port, addr) {
console.log(`message from ${addr}:${port}:`);
console.log(buf.toString());
},
},
});
const client = await Bun.udpSocket({});
client.send("Hello!", server.port, "127.0.0.1");Connections
UDP has no concept of a connection, but many UDP exchanges (especially as a client) involve only one peer. In that case you can connect the socket to that peer, which sets the destination address for every packet you send and restricts incoming packets to that peer.
const server = await Bun.udpSocket({
socket: {
data(socket, buf, port, addr) {
console.log(`message from ${addr}:${port}:`);
console.log(buf.toString());
},
},
});
const client = await Bun.udpSocket({
connect: {
port: server.port,
hostname: "127.0.0.1",
},
});
client.send("Hello");Connections are implemented at the operating system level, so they can also improve performance.
Send many packets at once using sendMany()
To send a large volume of packets without the overhead of a system call for each, batch them with sendMany().
For an unconnected socket, sendMany takes an array as its only argument. Each set of three array elements describes a packet:
the data to send, the target port, and the target address.
const socket = await Bun.udpSocket({});
// sends 'Hello' to 127.0.0.1:41234, and 'foo' to 1.1.1.1:53 in a single operation
socket.sendMany(["Hello", 41234, "127.0.0.1", "foo", 53, "1.1.1.1"]);With a connected socket, sendMany takes an array where each element is the data to send to the peer.
const socket = await Bun.udpSocket({
connect: {
port: 41234,
hostname: "localhost",
},
});
socket.sendMany(["foo", "bar", "baz"]);sendMany returns the number of packets successfully sent. Like send, it only takes valid IP addresses
as destinations and does not perform DNS resolution.
Handle backpressure
A packet you send may not fit into the operating system's packet buffer. You can detect that this has happened when:
sendreturnsfalsesendManyreturns a number smaller than the number of packets you specified. In this case, Bun calls thedrainsocket handler once the socket becomes writable again:
const socket = await Bun.udpSocket({
socket: {
drain(socket) {
// continue sending data
},
},
});Socket options
UDP sockets support setting various socket options:
const socket = await Bun.udpSocket({});
// Enable broadcasting to send packets to a broadcast address
socket.setBroadcast(true);
// Set the IP TTL (time to live) for outgoing packets
socket.setTTL(64);Multicast
Bun supports multicast operations for UDP sockets. Use addMembership and dropMembership to join and leave multicast groups:
const socket = await Bun.udpSocket({});
// Join a multicast group
socket.addMembership("224.0.0.1");
// Join with a specific interface
socket.addMembership("224.0.0.1", "192.168.1.100");
// Leave a multicast group
socket.dropMembership("224.0.0.1");Additional multicast options:
// Set TTL for multicast packets (number of network hops)
socket.setMulticastTTL(2);
// Control whether multicast packets loop back to the local socket
socket.setMulticastLoopback(true);
// Specify which interface to use for outgoing multicast packets
socket.setMulticastInterface("192.168.1.100");For source-specific multicast (SSM), use addSourceSpecificMembership and dropSourceSpecificMembership:
socket.addSourceSpecificMembership("10.0.0.1", "232.0.0.1");
socket.dropSourceSpecificMembership("10.0.0.1", "232.0.0.1");