การใช้ WebTransport

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

ข้อมูลเบื้องต้น

WebTransport คืออะไร

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

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

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

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

ต่อไปนี้เป็นรายการวิธีต่างๆ ที่นักพัฒนาซอฟต์แวร์อาจใช้ WebTransport

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

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

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

การรองรับเบราว์เซอร์

  • Chrome: 97
  • Edge: 97
  • Firefox: 114
  • Safari: ไม่รองรับ

แหล่งที่มา

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

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

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

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

WebTransport จะมาแทนที่ WebSocket ใช่ไหม

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

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

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

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

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

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

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

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

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

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

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

ลองเลย

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

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

การใช้ API

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

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

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

คุณเชื่อมต่อกับเซิร์ฟเวอร์ 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.then(() => {
  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 API

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

Getter ของ writeable จะแสดงผล WritableStream ซึ่งเว็บไคลเอ็นต์สามารถใช้เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ Getter ของ readable จะแสดงผล 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 ซึ่งจะแสดงผลพรอมต์สําหรับ 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.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

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

ไคลเอ็นต์เว็บสามารถสร้างโดยใช้เมธอด createBidirectionalStream() ของอินสแตนซ์ WebTransport ซึ่งจะแสดงผลพรอมต์สําหรับ 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

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

โพลีฟิลล์

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

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

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

ความคิดเห็น

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

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

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

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

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

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

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

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

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

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

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

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

ขอขอบคุณ

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

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