这是一个面向库作者和高级用例的低级 API。
启动服务器(Bun.listen())
使用 Bun.listen 启动一个 TCP 服务器:

server.ts
Bun.listen({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {}, // 收到来自客户端的消息
open(socket) {}, // 连接打开
close(socket, error) {}, // 连接关闭
drain(socket) {}, // 连接可写入更多数据
error(socket, error) {}, // 错误处理
},
});
在 Bun 中,一组处理函数是在服务器级别声明一次,而不是像 Node.js 的 EventEmitter 或 web 标准的 WebSocket API 那样,为每个连接分配回调函数。
server.ts
Bun.listen({
hostname: "localhost",
port: 8080,
socket: {
open(socket) {},
data(socket, data) {},
drain(socket) {},
close(socket, error) {},
error(socket, error) {},
},
});
对于性能敏感的服务器,为每个连接分配监听器会造成显著的垃圾回收压力并增加内存使用。相比之下,Bun 仅为每种事件分配一个处理函数,并在所有连接间共享。这是一个小优化,但积少成多。
可以在 open 事件处理器中为每个连接附加上下文数据。

server.ts
type SocketData = { sessionId: string };
Bun.listen<SocketData>({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {
socket.write(`${socket.data.sessionId}: ack`);
},
open(socket) {
socket.data = { sessionId: "abcd" };
},
},
});
要启用 TLS,传入包含 key 和 cert 字段的 tls 对象。

server.ts
Bun.listen({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {},
},
tls: {
// 可为字符串、BunFile、TypedArray、Buffer 或它们的数组
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
},
});
key 和 cert 字段期望的是 TLS 私钥和证书的内容。类型可以是字符串、BunFile、TypedArray 或 Buffer。

server.ts
Bun.listen({
// ...
tls: {
key: Bun.file("./key.pem"), // BunFile
key: fs.readFileSync("./key.pem"), // Buffer
key: fs.readFileSync("./key.pem", "utf8"), // 字符串
key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")], // 上述类型的数组
},
});
Bun.listen 的返回值是符合 TCPSocket 接口的服务器实例。

server.ts
const server = Bun.listen({
/* 配置 */
});
// 停止监听
// 参数表示是否关闭所有活动连接
server.stop(true);
// 让 Bun 进程即便服务器仍在监听也能退出
server.unref();
创建连接(Bun.connect())
使用 Bun.connect 连接到 TCP 服务器。通过 hostname 和 port 指定目标服务器。TCP 客户端的处理器集与 Bun.listen 相同,另加几个客户端专用的处理器。

server.ts
// 客户端
const socket = await Bun.connect({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {},
open(socket) {},
close(socket, error) {},
drain(socket) {},
error(socket, error) {},
// 客户端专用处理器
connectError(socket, error) {}, // 连接失败
end(socket) {}, // 服务器关闭连接
timeout(socket) {}, // 连接超时
},
});
要启用 TLS,设置 tls: true。
// 客户端
const socket = await Bun.connect({
// ... 配置
tls: true,
});
热重载
TCP 服务器和连接都能热重载新的处理器。
const server = Bun.listen({
/* 配置 */
});
// 为所有活动的服务器端连接重新加载处理器
server.reload({
socket: {
data() {
// 新的 'data' 处理器
},
},
});
当前,Bun 的 TCP 连接不会自动缓冲数据。对性能敏感的代码需要谨慎处理缓冲。例如,下面这样写:
socket.write("h");
socket.write("e");
socket.write("l");
socket.write("l");
socket.write("o");
性能会明显差于:
为简化此问题,可以使用 Bun 提供的 ArrayBufferSink,配合 {stream: true} 选项:

server.ts
import { ArrayBufferSink } from "bun";
const sink = new ArrayBufferSink();
sink.start({
stream: true,
highWaterMark: 1024,
});
sink.write("h");
sink.write("e");
sink.write("l");
sink.write("l");
sink.write("o");
queueMicrotask(() => {
const data = sink.flush();
const wrote = socket.write(data);
if (wrote < data.byteLength) {
// 如果连接满了,剩余数据放回缓冲区
sink.write(data.subarray(wrote));
}
});
缓冲合并(Corking)计划支持缓冲合并功能,但目前必须通过 drain 事件手动管理背压。