各位观众,各位朋友,大家好!我是今天的主讲人,咱们今天聊聊这个听起来有点科幻,但其实离我们已经不远的 WebTransport。别被它那个“HTTP/3 over UDP”的头衔吓着,其实它就是个更快的、更灵活的“网页版实时通信管道”。
WebTransport:告别 WebSocket,拥抱 UDP 的未来
你可能听说过 WebSocket,它让网页能和服务器建立一个长连接,实现实时通信。但是,WebSocket 毕竟还是基于 TCP 的,TCP 有队头阻塞问题(Head-of-Line Blocking),一旦前面的数据包丢了,后面的数据包也得跟着等着,这在实时性要求高的场景下可不行。
WebTransport 呢,它直接基于 UDP,UDP 可是个“我发送,我快乐,丢了就丢了”的协议。当然,直接用 UDP 肯定不行,得加点东西保证可靠性。WebTransport 用的是 HTTP/3 的 QUIC 协议,QUIC 在 UDP 的基础上实现了可靠传输、拥塞控制、多路复用等功能,还自带加密,简直是 UDP 的“豪华升级版”。
WebTransport 的优势:
- 低延迟: 基于 UDP,避免了 TCP 的队头阻塞,延迟更低。
- 多路复用: 可以在一个连接上建立多个独立的流,互不影响。
- 可靠性与不可靠性并存: 既可以发送可靠的数据,也可以发送不可靠的数据,满足不同场景的需求。
- 双向通信: 客户端和服务器可以随时互相发送数据。
- 支持连接迁移: 即使客户端的网络发生变化,连接也能保持,不会中断。
WebTransport 的应用场景:
- 在线游戏: 实时同步游戏状态,延迟是关键。
- 实时音视频: 视频会议、直播,需要低延迟和高带宽。
- 远程控制: 远程桌面、远程调试,需要快速响应。
- 数据推送: 服务器主动向客户端推送数据,例如实时股票行情。
WebTransport 的核心概念:
- WebTransport: 整个连接对象,负责建立和管理连接。
- Streams(流): 在 WebTransport 连接上建立的单向或双向数据通道。分为:
- Unidirectional Streams(单向流): 只能由一方发送数据,另一方接收数据。
- Bidirectional Streams(双向流): 双方都可以发送和接收数据。
- Datagrams(数据报): 无需建立流,直接发送的 UDP 数据包,不可靠。
WebTransport 的代码示例:
咱们来点干货,看看 WebTransport 的代码怎么写。
服务器端 (Node.js):
首先,你需要一个支持 HTTP/3 的服务器。这里我们用 node-webtransport
这个库。
const {
WebTransportServer,
WebTransport,
WebTransportSession,
WebTransportDatagramWriter,
WebTransportStream,
} = require('node-webtransport');
const fs = require('fs');
const key = fs.readFileSync('localhost.key');
const cert = fs.readFileSync('localhost.crt');
const server = new WebTransportServer({
port: 4433,
serverOptions: {
key,
cert,
}
});
server.listen();
server.on('session', (session) => {
console.log('New session');
session.on('stream', async (stream) => {
console.log('New stream');
// 读取客户端发送的数据
const reader = stream.readable.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
console.log('Received:', new TextDecoder().decode(value));
// 将数据返回给客户端
const writer = stream.writable.getWriter();
await writer.write(value);
await writer.close();
}
} catch (e) {
console.error(e);
} finally {
reader.releaseLock();
}
});
session.datagrams.readable.pipeTo(new WritableStream({
write(chunk) {
console.log("Datagram received:", new TextDecoder().decode(chunk));
}
}))
});
console.log('WebTransport server listening on port 4433');
这段代码创建了一个 WebTransport 服务器,监听在 4433 端口。当有新的客户端连接时,会触发 session
事件。当客户端创建新的流时,会触发 stream
事件。服务器会读取客户端发送的数据,并将其返回给客户端。同时监听datagrams,接收客户端发来的不可靠数据。
客户端 (JavaScript):
async function connectWebTransport() {
try {
const wt = new WebTransport("https://localhost:4433/"); // 替换为你的服务器地址
await wt.ready;
console.log("Connected to WebTransport server!");
// 创建一个双向流
const stream = await wt.createBidirectionalStream();
console.log("Created bidirectional stream");
// 向服务器发送数据
const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode("Hello from the client!"));
await writer.close();
console.log("Sent data to server");
// 读取服务器返回的数据
const reader = stream.readable.getReader();
const { value, done } = await reader.read();
reader.releaseLock();
if (done) {
console.log("Stream closed by server");
} else {
console.log("Received from server:", new TextDecoder().decode(value));
}
//发送datagram
const datagramWriter = wt.datagrams.writable.getWriter();
await datagramWriter.write(new TextEncoder().encode("Hello Datagram!"));
await datagramWriter.close();
// 关闭连接
await wt.close();
console.log("WebTransport connection closed");
} catch (e) {
console.error("WebTransport connection failed:", e);
}
}
connectWebTransport();
这段代码连接到 WebTransport 服务器,创建一个双向流,向服务器发送数据,并读取服务器返回的数据。最后发送一个datagram,并关闭连接。
注意事项:
- HTTPS: WebTransport 必须使用 HTTPS,因为 QUIC 需要加密。
- 证书: 你需要生成一个自签名证书,或者使用有效的 SSL 证书。
- 浏览器支持: 目前 WebTransport 还在实验阶段,需要启用浏览器的实验性功能。例如,在 Chrome 中,你需要启用
chrome://flags/#enable-experimental-web-platform-features
。 - node-webtransport: 这个库目前还在积极开发中,API 可能会发生变化。
Unidirectional Streams (单向流) 和 Bidirectional Streams (双向流) 的比较:
特性 | Unidirectional Stream | Bidirectional Stream |
---|---|---|
方向 | 单向 (只能由一方发送,另一方接收) | 双向 (双方都可以发送和接收) |
创建者 | 可以由客户端或服务器创建 | 可以由客户端或服务器创建 |
用途 | 适用于单向数据传输,例如服务器推送数据、客户端上传文件 | 适用于双向交互,例如客户端发送请求,服务器返回响应 |
代码示例 (客户端) | wt.createUnidirectionalStream() |
wt.createBidirectionalStream() |
Datagrams (数据报) 的使用:
Datagrams 是一种不可靠的传输方式,适用于对延迟非常敏感,但对数据丢失不敏感的场景。例如,在在线游戏中,可以用来发送玩家的位置信息。
// 发送 Datagram (客户端)
const datagramWriter = wt.datagrams.writable.getWriter();
await datagramWriter.write(new TextEncoder().encode("Player position: x=10, y=20"));
await datagramWriter.close();
// 接收 Datagram (服务器端)
session.datagrams.readable.pipeTo(new WritableStream({
write(chunk) {
console.log("Datagram received:", new TextDecoder().decode(chunk));
}
}))
WebTransport 的未来:
WebTransport 还在发展中,但它代表了 Web 实时通信的未来。随着浏览器和服务器的支持越来越完善,WebTransport 将会在更多的场景中得到应用。
一些有用的资源:
- node-webtransport: https://github.com/DavidDerkse/node-webtransport
- WebTransport 规范: https://wicg.github.io/web-transport/
总结:
WebTransport 是一个令人兴奋的新技术,它为 Web 实时通信带来了更高的性能和更大的灵活性。虽然目前还在实验阶段,但它已经展现出了巨大的潜力。如果你对实时通信感兴趣,不妨关注一下 WebTransport,也许它会给你带来惊喜。
Q & A:
好了,今天的讲座就到这里。大家有什么问题吗? 欢迎提问!