การใช้ WebTransport

WebTransport เป็น API ที่มีการรับส่งข้อความแบบไคลเอ็นต์-เซิร์ฟเวอร์แบบสองทิศทางที่มีเวลาในการตอบสนองต่ำ ดูข้อมูลเพิ่มเติมเกี่ยวกับกรณีการใช้งานและวิธีแสดงความคิดเห็นเกี่ยวกับการใช้งานในอนาคต

ฉากหลัง

WebTransport คืออะไร

WebTransport คือ Web API ที่ใช้โปรโตคอล HTTP/3 เป็นการรับส่งข้อมูลแบบ 2 ทาง โดยมีไว้สำหรับการสื่อสารแบบ 2 ทางระหว่างเว็บไคลเอ็นต์กับเซิร์ฟเวอร์ HTTP/3 โดยรองรับการส่งข้อมูลทั้งแบบไม่น่าเชื่อถือผ่าน API แบบ Datagram และแบบน่าเชื่อถือผ่าน API แบบสตรีม

ดาต้าแกรมเหมาะสำหรับการส่งและรับข้อมูลที่ไม่จำเป็นต้องมีการรับประกันการนำส่งที่เข้มงวด แพ็กเก็ตข้อมูลแต่ละรายการมีขนาดจำกัดตามหน่วยส่งสูงสุด (MTU) ของการเชื่อมต่อพื้นฐาน และอาจส่งสำเร็จหรือไม่ก็ได้ และหากมีการโอนข้อมูล แพ็กเก็ตอาจมาถึงตามลำดับใดก็ได้ ลักษณะเหล่านี้ทำให้ API ของ Datagram เหมาะอย่างยิ่งสำหรับการส่งข้อมูลที่มีเวลาในการตอบสนองต่ำและส่งข้อมูลอย่างเต็มที่ คุณอาจมองว่า Datagram เป็นข้อความUser Datagram Protocol (UDP) แต่มีการเข้ารหัสและควบคุมความแออัด

ในทางตรงกันข้าม API สตรีมจะให้การโอนข้อมูลที่เชื่อถือได้และมีการจัดลำดับ ซึ่งเหมาะกับสถานการณ์ที่คุณต้องส่งหรือรับสตรีมข้อมูลที่เรียงลำดับแล้วอย่างน้อย 1 รายการ การใช้สตรีม WebTransport หลายรายการจะคล้ายกับการสร้างการเชื่อมต่อ TCP หลายรายการ แต่เนื่องจาก HTTP/3 ใช้โปรโตคอล QUIC ที่มีน้ำหนักเบากว่าอยู่เบื้องหลัง จึงสามารถเปิดและปิดได้โดยไม่ต้องมีค่าใช้จ่ายมากนัก

กรณีการใช้งาน

นี่คือรายการเล็กๆ ของวิธีที่นักพัฒนาแอปอาจใช้ WebTransport

  • การส่งสถานะเกมเป็นระยะๆ โดยมีเวลาในการตอบสนองน้อยที่สุดไปยังเซิร์ฟเวอร์ผ่านข้อความขนาดเล็กที่เชื่อถือไม่ได้และเรียงลำดับไม่ถูกต้อง
  • รับสตรีมสื่อที่ส่งจากเซิร์ฟเวอร์โดยมีความหน่วงน้อยที่สุด โดยไม่ขึ้นอยู่กับสตรีมข้อมูลอื่นๆ
  • รับการแจ้งเตือนที่พุชจากเซิร์ฟเวอร์ขณะที่หน้าเว็บเปิดอยู่

เรายินดีที่จะรับฟังเพิ่มเติมเกี่ยวกับวิธีที่คุณวางแผนที่จะใช้ WebTransport

การสนับสนุนเบราว์เซอร์

Browser Support

  • Chrome: 97.
  • Edge: 97.
  • Firefox: 114.
  • Safari: behind a flag.

Source

เช่นเดียวกับฟีเจอร์ทั้งหมดที่เบราว์เซอร์บางตัวไม่รองรับ การเขียนโค้ดแบบป้องกันผ่านการตรวจหาฟีเจอร์ถือเป็นแนวทางปฏิบัติแนะนำ

สถานะปัจจุบัน

ขั้นตอน สถานะ
1. สร้างวิดีโออธิบาย เสร็จสมบูรณ์
2. สร้างร่างข้อกำหนดเบื้องต้น เสร็จสมบูรณ์
3. รวบรวมความคิดเห็นและออกแบบซ้ำ เสร็จสมบูรณ์
4. ช่วงทดลองใช้จากต้นทาง เสร็จสมบูรณ์
5. เปิดตัว Chromium 97

ความสัมพันธ์ของ WebTransport กับเทคโนโลยีอื่นๆ

WebTransport ใช้แทน WebSocket ได้ไหม

อาจจะได้ มีกรณีการใช้งานที่ WebSockets หรือ WebTransport อาจเป็นโปรโตคอลการสื่อสารที่ถูกต้องในการใช้งาน

การสื่อสารผ่าน WebSocket ได้รับการออกแบบมาให้มีสตรีมข้อความเดียวที่เชื่อถือได้และเรียงตามลำดับ ซึ่งเหมาะสำหรับความต้องการในการสื่อสารบางประเภท หากต้องการลักษณะดังกล่าว API สตรีมของ WebTransport ก็สามารถให้ได้เช่นกัน ในทางตรงกันข้าม API ของ Datagram ของ WebTransport จะให้การนำส่งที่มีเวลาในการตอบสนองต่ำโดยไม่มีการรับประกันความน่าเชื่อถือหรือการจัดลำดับ จึงไม่ใช่การแทนที่ WebSocket โดยตรง

การใช้ WebTransport ผ่าน Datagram API หรือผ่านอินสแตนซ์ Streams API ที่ทำงานพร้อมกันหลายรายการหมายความว่าคุณไม่ต้องกังวลเกี่ยวกับการบล็อกส่วนหัวของบรรทัด ซึ่งอาจเป็นปัญหาที่เกิดขึ้นกับ WebSocket นอกจากนี้ การสร้างการเชื่อมต่อใหม่ยังช่วยเพิ่มประสิทธิภาพได้ด้วย เนื่องจากแฮนด์เชค QUIC ที่อยู่เบื้องหลังนั้นเร็วกว่าการเริ่มต้น TCP ผ่าน TLS

WebTransport เป็นส่วนหนึ่งของข้อกำหนดฉบับร่างใหม่ และด้วยเหตุนี้ ระบบนิเวศ WebSocket รอบๆ ไลบรารีไคลเอ็นต์และเซิร์ฟเวอร์จึงมีความแข็งแกร่งมากกว่าในปัจจุบัน หากคุณต้องการสิ่งที่ใช้งานได้ "ทันที" กับการตั้งค่าเซิร์ฟเวอร์ทั่วไปและรองรับไคลเอ็นต์เว็บอย่างกว้างขวาง WebSocket เป็นตัวเลือกที่ดีกว่าในปัจจุบัน

WebTransport เหมือนกับ UDP Socket API ไหม

ไม่ WebTransport ไม่ใช่ UDP Socket API แม้ว่า WebTransport จะใช้ HTTP/3 ซึ่งใช้ UDP "เบื้องหลัง" แต่ WebTransport มีข้อกำหนดเกี่ยวกับการเข้ารหัสและการควบคุมความแออัดที่ทำให้ WebTransport เป็นมากกว่า API ซ็อกเก็ต UDP พื้นฐาน

WebTransport เป็นทางเลือกแทนช่องข้อมูล WebRTC หรือไม่

ได้ สำหรับการเชื่อมต่อไคลเอ็นต์-เซิร์ฟเวอร์ WebTransport มีพร็อพเพอร์ตี้หลายอย่างเหมือนกับช่องข้อมูล WebRTC แม้ว่าโปรโตคอลพื้นฐานจะแตกต่างกัน

โดยทั่วไป การเรียกใช้เซิร์ฟเวอร์ที่รองรับ HTTP/3 จะต้องมีการตั้งค่าและการกำหนดค่าน้อยกว่าการดูแลเซิร์ฟเวอร์ WebRTC ซึ่งเกี่ยวข้องกับการทำความเข้าใจโปรโตคอลหลายรายการ (ICE, DTLS และ SCTP) เพื่อให้ได้การรับส่งที่ใช้งานได้ WebRTC มีองค์ประกอบที่เคลื่อนไหวได้อีกมากมายซึ่งอาจทำให้การเจรจาระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ไม่สำเร็จ

WebTransport API ได้รับการออกแบบโดยคำนึงถึง Use Case ของนักพัฒนาเว็บ และควรให้ความรู้สึกเหมือนการเขียนโค้ดแพลตฟอร์มเว็บสมัยใหม่มากกว่าการใช้อินเทอร์เฟซช่องข้อมูลของ WebRTC WebTransport รองรับภายใน Web Worker ซึ่งต่างจาก WebRTC ทำให้คุณสามารถสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ได้โดยไม่ขึ้นอยู่กับหน้า HTML ที่ระบุ เนื่องจาก WebTransport แสดงอินเทอร์เฟซที่สอดคล้องกับ Streams จึงรองรับการเพิ่มประสิทธิภาพเกี่ยวกับแรงดันย้อนกลับ

อย่างไรก็ตาม หากคุณมีการตั้งค่าไคลเอ็นต์/เซิร์ฟเวอร์ WebRTC ที่ใช้งานได้อยู่แล้วและพึงพอใจกับการตั้งค่าดังกล่าว การเปลี่ยนไปใช้ WebTransport อาจไม่ได้มีข้อดีมากนัก

ลองเลย

วิธีที่ดีที่สุดในการทดลองใช้ WebTransport คือการเริ่มต้นเซิร์ฟเวอร์ HTTP/3 ที่เข้ากันได้ จากนั้นคุณจะใช้หน้านี้กับไคลเอ็นต์ JavaScript พื้นฐานเพื่อลองใช้การสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ได้

นอกจากนี้ ยังมีเซิร์ฟเวอร์ Echo ที่ชุมชนดูแลอยู่ที่ webtransport.day

การใช้ API

WebTransport ได้รับการออกแบบบนพื้นฐานของแพลตฟอร์มเว็บที่ทันสมัย เช่น Streams API โดยจะอาศัยสัญญาเป็นอย่างมาก และทำงานได้ดีกับ async และ await

การใช้งาน WebTransport ใน Chromium ปัจจุบันรองรับการรับส่งข้อมูล 3 ประเภท ได้แก่ Datagram รวมถึงสตรีมแบบทิศทางเดียวและแบบสองทิศทาง

การเชื่อมต่อกับเซิร์ฟเวอร์

คุณเชื่อมต่อกับเซิร์ฟเวอร์ HTTP/3 ได้โดยการสร้างWebTransportอินสแตนซ์ รูปแบบของ URL ควรเป็น https คุณต้องระบุหมายเลขพอร์ตอย่างชัดเจน

คุณควรใช้สัญญา ready เพื่อรอให้ระบบสร้างการเชื่อมต่อ ระบบจะไม่ดำเนินการตามสัญญานี้จนกว่าการตั้งค่าจะเสร็จสมบูรณ์ และจะปฏิเสธหากการเชื่อมต่อล้มเหลวในขั้นตอน QUIC/TLS

closed สัญญาจะดำเนินการให้เสร็จสมบูรณ์เมื่อการเชื่อมต่อปิดตามปกติ และจะปฏิเสธหากการปิดนั้นไม่คาดคิด

หากเซิร์ฟเวอร์ปฏิเสธการเชื่อมต่อเนื่องจากข้อผิดพลาดการระบุไคลเอ็นต์ (เช่น เส้นทางของ URL ไม่ถูกต้อง) จะทำให้ closed ปฏิเสธ ในขณะที่ ready ยังคงไม่ได้รับการแก้ไข

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.t>hen(() = {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((>error) = {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

Datagram APIs

เมื่อมีอินสแตนซ์ WebTransport ที่เชื่อมต่อกับเซิร์ฟเวอร์แล้ว คุณจะใช้เพื่อส่งและรับข้อมูลแบบแยกส่วนที่เรียกว่าดาต้าแกรมได้

writeable Getter จะแสดงผล WritableStream ซึ่งเว็บไคลเอ็นต์ใช้เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ได้ readable Getter จะแสดง ReadableStream ซึ่งช่วยให้คุณรับฟังข้อมูลจากเซิร์ฟเวอร์ได้ ทั้ง 2 สตรีมนี้ไม่น่าเชื่อถือโดยธรรมชาติ ดังนั้นจึงเป็นไปได้ที่เซิร์ฟเวอร์จะไม่ได้รับข้อมูลที่คุณเขียน และในทางกลับกัน

สตรีมทั้ง 2 ประเภทใช้อินสแตนซ์ Uint8Array สำหรับการโอนข้อมูล

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

Streams API

เมื่อเชื่อมต่อกับเซิร์ฟเวอร์แล้ว คุณยังใช้ WebTransport เพื่อส่งและรับข้อมูลผ่าน Streams API ได้ด้วย

โดยแต่ละก้อนของสตรีมทั้งหมดคือ Uint8Array สตรีมเหล่านี้เชื่อถือได้ ซึ่งต่างจาก Datagram API แต่แต่ละสตรีมเป็นอิสระต่อกัน จึงไม่รับประกันลำดับข้อมูลในสตรีม

WebTransportSendStream

ไคลเอ็นต์ของเว็บจะสร้าง WebTransportSendStream โดยใช้วิธี createUnidirectionalStream() ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผล Promise สำหรับ WebTransportSendStream

ใช้เมธอด close() ของ WritableStreamDefaultWriter เพื่อปิดสตรีม HTTP/3 ที่เชื่อมโยง เบราว์เซอร์จะพยายามส่งข้อมูลที่รอดำเนินการทั้งหมดก่อนที่จะปิดสตรีมที่เชื่อมโยงจริงๆ

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

ในทำนองเดียวกัน ให้ใช้วิธี abort() ของ WritableStreamDefaultWriter เพื่อส่ง RESET_STREAM ไปยังเซิร์ฟเวอร์ เมื่อใช้ abort() เบราว์เซอร์อาจทิ้งข้อมูลที่รอดำเนินการซึ่งยังไม่ได้ส่ง

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

เซิร์ฟเวอร์จะเริ่ม WebTransportReceiveStream การขอ WebTransportReceiveStream เป็นกระบวนการ 2 ขั้นตอนสำหรับเว็บไคลเอ็นต์ ก่อนอื่น ฟังก์ชันจะเรียกแอตทริบิวต์ incomingUnidirectionalStreams ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผล ReadableStream ReadableStream แต่ละก้อนนั้นเป็น WebTransportReceiveStream ที่ใช้เพื่ออ่านอินสแตนซ์ Uint8Array ที่เซิร์ฟเวอร์ส่งมาได้

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

คุณตรวจหาการปิดสตรีมได้โดยใช้สัญญา closed ของ ReadableStreamDefaultReader เมื่อสตรีม HTTP/3 พื้นฐานปิดด้วยบิต FIN ระบบจะทำตามclosedสัญญาหลังจากอ่านข้อมูลทั้งหมดแล้ว เมื่อสตรีม HTTP/3 ปิดอย่างกะทันหัน (เช่น โดย RESET_STREAM) สัญญา closed จะปฏิเสธ

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).ca>tch(() = {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

WebTransportBidirectionalStream อาจสร้างโดยเซิร์ฟเวอร์หรือไคลเอ็นต์

ไคลเอ็นต์ของเว็บสร้างได้โดยใช้วิธี createBidirectionalStream() ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผล Promise สำหรับ WebTransportBidirectionalStream

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

คุณสามารถฟัง WebTransportBidirectionalStream ที่เซิร์ฟเวอร์สร้างขึ้นด้วยแอตทริบิวต์ incomingBidirectionalStreams ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผล ReadableStream ReadableStream แต่ละก้อนจะเป็น WebTransportBidirectionalStream

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

WebTransportBidirectionalStream เป็นเพียงการรวมกันของ WebTransportSendStream และ WebTransportReceiveStream ตัวอย่างจาก 2 ส่วนก่อนหน้าจะอธิบายวิธีใช้แต่ละรายการ

ตัวอย่างเพิ่มเติม

ข้อกําหนดฉบับร่างของ WebTransport มีตัวอย่างเพิ่มเติมแบบอินไลน์อีกหลายรายการ พร้อมด้วยเอกสารประกอบทั้งหมดสําหรับเมธอดและพร็อพเพอร์ตี้ทั้งหมด

WebTransport ในเครื่องมือสำหรับนักพัฒนาเว็บของ Chrome

ขออภัย ขณะนี้ DevTools ของ Chrome ยังไม่รองรับ WebTransport คุณสามารถ "ติดดาว" ปัญหานี้ใน Chrome เพื่อรับการแจ้งเตือนเกี่ยวกับการอัปเดตอินเทอร์เฟซ DevTools

Polyfill

มี Polyfill (หรือ Ponyfill ที่มีฟังก์ชันการทำงานเป็นโมดูลแบบสแตนด์อโลนที่คุณใช้ได้) ชื่อ webtransport-ponyfill-websocket ซึ่งใช้ฟีเจอร์บางอย่างของ WebTransport อ่านข้อจำกัดในREADMEของโปรเจ็กต์อย่างละเอียดเพื่อพิจารณาว่าโซลูชันนี้ใช้ได้กับ Use Case ของคุณหรือไม่

ข้อควรพิจารณาด้านความเป็นส่วนตัวและความปลอดภัย

ดูคำแนะนำที่เชื่อถือได้ในส่วนที่เกี่ยวข้องของข้อกำหนดฉบับร่าง

ความคิดเห็น

ทีม Chrome อยากทราบความคิดเห็นและประสบการณ์การใช้งาน API นี้ของคุณ

ความคิดเห็นเกี่ยวกับการออกแบบ API

มีอะไรเกี่ยวกับ API ที่ไม่สะดวกหรือทำงานไม่เป็นไปตามที่คาดไว้ไหม หรือมีสิ่งใดที่ขาดหายไปซึ่งคุณต้องใช้ในการนำไอเดียไปใช้ไหม

แจ้งปัญหาในที่เก็บ GitHub ของ Web Transport หรือแสดงความคิดเห็นเกี่ยวกับปัญหาที่มีอยู่

หากพบปัญหาในการติดตั้งใช้งาน

หากพบข้อบกพร่องในการใช้งาน Chrome

ยื่นข้อบกพร่องที่ https://new.crbug.com โดยระบุรายละเอียดให้มากที่สุดเท่าที่จะทำได้ พร้อมด้วยวิธีการง่ายๆ ในการจำลองข้อบกพร่อง

หากมีแผนจะใช้ API

การสนับสนุนแบบสาธารณะของคุณช่วยให้ Chrome จัดลําดับความสําคัญของฟีเจอร์ต่างๆ และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นๆ เห็นว่าการสนับสนุนฟีเจอร์เหล่านี้มีความสําคัญเพียงใด

  • ส่งทวีตถึง @ChromiumDev โดยใช้แฮชแท็ก #WebTransport และรายละเอียดเกี่ยวกับสถานที่และวิธีที่คุณใช้

การสนทนาทั่วไป

คุณใช้ web-transport-dev Google Group สำหรับคำถามหรือปัญหาทั่วไปที่ไม่ได้อยู่ในหมวดหมู่อื่นๆ ได้

คำขอบคุณ

บทความนี้มีข้อมูลจากคำอธิบายเกี่ยวกับ WebTransport, ข้อกำหนดฉบับร่าง และเอกสารการออกแบบที่เกี่ยวข้อง ขอขอบคุณผู้เขียนที่เกี่ยวข้องที่วางรากฐานดังกล่าว

รูปภาพหลักในโพสต์นี้ถ่ายโดย Robin Pierre ใน Unsplash