使用 Bun 的原生 TCP API 來實作效能敏感的系統,例如資料庫客戶端、遊戲伺服器,或任何需要透過 TCP(而非 HTTP)進行通訊的系統。這是一個底層 API,專為程式庫作者和進階使用案例而設計。
啟動伺服器 (Bun.listen()
)
要使用 Bun.listen
啟動 TCP 伺服器
Bun.listen({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {}, // message received from client
open(socket) {}, // socket opened
close(socket, error) {}, // socket closed
drain(socket) {}, // socket ready for more data
error(socket, error) {}, // error handler
},
});
專為速度設計的 API
內容相關的資料可以在 open
處理常式中附加到通訊端。
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
物件。
Bun.listen({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {},
},
tls: {
// can be string, BunFile, TypedArray, Buffer, or array thereof
key: Bun.file("./key.pem"),
cert: Bun.file("./cert.pem"),
},
});
key
和 cert
欄位預期您的 TLS 金鑰和憑證的內容。這可以是字串、BunFile
、TypedArray
或 Buffer
。
Bun.listen({
// ...
tls: {
// BunFile
key: Bun.file("./key.pem"),
// Buffer
key: fs.readFileSync("./key.pem"),
// string
key: fs.readFileSync("./key.pem", "utf8"),
// array of above
key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
},
});
Bun.listen
的結果是一個符合 TCPSocket
介面的伺服器。
const server = Bun.listen({
/* config*/
});
// stop listening
// parameter determines whether active connections are closed
server.stop(true);
// let Bun process exit even if server is still listening
server.unref();
建立連線 (Bun.connect()
)
使用 Bun.connect
連接到 TCP 伺服器。使用 hostname
和 port
指定要連線的伺服器。TCP 客戶端可以定義與 Bun.listen
相同的處理常式集合,外加一些客戶端特定的處理常式。
// The client
const socket = await Bun.connect({
hostname: "localhost",
port: 8080,
socket: {
data(socket, data) {},
open(socket) {},
close(socket, error) {},
drain(socket) {},
error(socket, error) {},
// client-specific handlers
connectError(socket, error) {}, // connection failed
end(socket) {}, // connection closed by server
timeout(socket) {}, // connection timed out
},
});
要要求 TLS,請指定 tls: true
。
// The client
const socket = await Bun.connect({
// ... config
tls: true,
});
熱重載
TCP 伺服器和通訊端都可以使用新的處理常式進行熱重載。
const server = Bun.listen({ /* config */ })
// reloads handlers for all active server-side sockets
server.reload({
socket: {
data(){
// new 'data' handler
}
}
})
const socket = await Bun.connect({ /* config */ })
socket.reload({
data(){
// new 'data' handler
}
})
緩衝處理
目前,Bun 中的 TCP 通訊端不緩衝資料。對於效能敏感的程式碼,仔細考慮緩衝處理非常重要。例如,這個
socket.write("h");
socket.write("e");
socket.write("l");
socket.write("l");
socket.write("o");
...效能明顯比這個差
socket.write("hello");
為了簡化此流程,目前請考慮使用 Bun 的 ArrayBufferSink
並搭配 {stream: true}
選項
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) {
// put it back in the sink if the socket is full
sink.write(data.subarray(wrote));
}
});
Corking — 計劃支援 corking,但在這段期間,必須使用 drain
處理常式手動管理反壓。