שימוש ב-WebTransport

WebTransport הוא ממשק API עם זמן אחזור קצר, העברת הודעות דו-כיווניות לשרת לקוח. מידע נוסף על התרחישים לדוגמה שלו ואיך לשלוח משוב על העתיד של ההטמעה.

רקע

מה זה WebTransport?

WebTransport הוא ממשק API לאינטרנט שמשתמש בפרוטוקול HTTP/3 כהעברה דו-כיוונית. הוא מיועד לתקשורת דו-כיוונית בין לקוח אינטרנט לבין שרת HTTP/3. הוא תומך בשליחת נתונים באופן לא מהימן דרך ממשקי API של datagram וגם באמצעות ממשקי API של סטרימינג.

Datagram הוא כלי אידיאלי לשליחה ולקבלה של נתונים שאינם מתחייבים היטב למסירה. הגודל של חבילות נתונים בודדות מוגבל בהתאם ליחידת ההעברה המקסימלית (MTU) של החיבור הבסיסי, וייתכן שהן יועברו בהצלחה או לא יועברו, ואם הן מועברות, הן עשויות להגיע בסדר שרירותי. המאפיינים האלה הופכים את ממשקי ה-API של datagram אידיאליים להעברת נתונים עם זמן אחזור קצר ועם הביצועים הטובים ביותר. אפשר להסתכל על גרם נתונים כהודעות User Datagram Protocol (UDP), אבל הן מוצפנות עם בקרת עומס.

לעומת זאת, ממשקי ה-API של הסטרימינג מספקים העברת נתונים מהימנה ומסודרת. הם מתאימים לתרחישים שבהם צריך לשלוח או לקבל לפחות מקור אחד של נתונים מסודרים. שימוש במספר שידורים של WebTransport מקביל ליצירת מספר חיבורי TCP, אבל מכיוון ש-HTTP/3 משתמש בפרוטוקול QUIC הקומפקטי יותר לעומק, כך שאפשר לפתוח ולסגור אותם בלי תקורה גדולה מדי.

תרחישים לדוגמה

זוהי רשימה קטנה של הדרכים האפשריות שבהן מפתחים יכולים להשתמש ב-WebTransport.

  • שליחת מצב המשחק במרווחי זמן קבועים עם זמן אחזור מינימלי אל השרת באמצעות הודעות קטנות, לא אמינות, שאינן בסדר.
  • קבלת שידורי מדיה בדחיפה משרת עם זמן אחזור מינימלי, ללא קשר למקורות נתונים אחרים.
  • קבלת התראות שנשלחו בדחיפה משרת בזמן שדף אינטרנט פתוח.

נשמח לקבל מידע נוסף על אופן השימוש שלכם ב-WebTransport.

תמיכה בדפדפנים

תמיכה בדפדפן

  • Chrome: 97.
  • קצה: 97.
  • Firefox: 114.
  • Safari: לא נתמך.

מקור

בדומה לתכונות שלא כוללות תמיכה אוניברסלית בדפדפנים, השיטה המומלצת היא תכנות הגנתי באמצעות זיהוי תכונות.

הסטטוס הנוכחי

שלב סטטוס
1. יצירת הסבר הושלם
2. יצירת טיוטה ראשונית של מפרט הושלם
3. קבלת משוב ושימוש בתכנון חוזר התשובה מלאה
4. גרסת מקור לניסיון התשובה מלאה
5. הפעלה Chromium 97

הקשר של WebTransport לטכנולוגיות אחרות

האם WebTransport הוא תחליף ל-WebSockets?

אולי. יש תרחישים לדוגמה שבהם WebSockets או WebTransport עשויים להיות פרוטוקולי תקשורת תקינים לשימוש.

מודל התקשורת של WebSockets מבוסס על רצף הודעות יחיד ואמין ומסודר, וזה בסדר לסוגים מסוימים של צורכי תקשורת. אם אתם צריכים את המאפיינים האלה, גם ממשקי ה-API של עדכוני התוכן ב-WebTransport יכולים לספק אותם. לעומת זאת, ממשקי ה-API של Datagram ב-WebTransport מספקים זמן אחזור קצר, בלי להבטיח אמינות או הזמנה. לכן הם לא תחליף באופן ישיר ל-WebSockets.

השימוש ב-WebTransport באמצעות ממשקי ה-API מסוג datagram או באמצעות מספר מכונות בו-זמנית של Streams API, מאפשר לכם לא לחשוש מחסימת תחילת השורה, שעלולה להיות בעיה ב-WebSockets. בנוסף, יש יתרונות לשיפור הביצועים כשיוצרים חיבורים חדשים, כי לחיצת היד הבסיסית של 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 תוכנן מתוך מחשבה על תרחישים לדוגמה של מפתחי אתרים, והוא דומה יותר לכתיבת קוד מודרני של פלטפורמת אינטרנט מאשר לשימוש בממשקי ערוץ הנתונים של WebRTC. בניגוד ל-WebRTC, WebTransport נתמך בתוך Web Workers, שמאפשר לבצע תקשורת בין שרתים לקוח ללא תלות בדף HTML נתון. מכיוון ש-WebTransport חושף ממשק שתואם ל-Streams, הוא תומך באופטימיזציה של backpressure.

עם זאת, אם כבר יש לכם הגדרה תקינה של לקוח/שרת WebRTC, לשביעות רצונך, ייתכן שהמעבר ל-WebTransport לא יציע הרבה יתרונות.

רוצה לנסות?

הדרך הטובה ביותר להתנסות ב-WebTransport היא להפעיל שרת HTTP/3 תואם. לאחר מכן אפשר להשתמש בדף הזה עם לקוח JavaScript בסיסי כדי לנסות תקשורת בין לקוח לשרת.

בנוסף, שרת הד בניהול הקהילה זמין ב-webtransport.day.

שימוש ב-API

WebTransport תוכנן על גבי מרכיבים מודרניים של פלטפורמות אינטרנט, כמו Streams API. הוא מסתמך בעיקר על הבטחות, ומשתלב היטב עם async ועם await.

ההטמעה הנוכחית של WebTransport ב-Chromium תומכת בשלושה סוגים שונים של תנועה: Datagrams, שידורים חד-כיווניים ודו-כיווניים.

התחברות לשרת

אפשר להתחבר לשרת 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;

ממשקי API של Datagram

כשיש לכם מכונת WebTransport שמחוברת לשרת, אתם יכולים להשתמש בה כדי לשלוח ולקבל קטעי נתונים נפרדים שנקראים datagrams.

ה-Getter של writeable מחזיר את הערך WritableStream, ולקוח אינטרנט יכול להשתמש בו כדי לשלוח נתונים לשרת. התו readable מחזיר ReadableStream, וכך מאפשר לך להאזין לנתונים מהשרת. שני מקורות הנתונים לא מהימנים מטבעם, ולכן ייתכן שהנתונים שתכתבו לא יתקבלו על ידי השרת, ולהיפך.

שני סוגי מקורות הנתונים משתמשים במכונות 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);
}

ממשקי API של סטרימינג

אחרי שמתחברים לשרת, אפשר להשתמש ב-WebTransport גם כדי לשלוח ולקבל נתונים דרך ממשקי ה-API של Streams.

כל מקטע מכל עדכוני התוכן הוא Uint8Array. בניגוד לממשקי ה-API של Datagram, מקורות הנתונים האלה מהימנים. עם זאת, כל מקור נתונים הוא עצמאי, ולכן סדר הנתונים בין מקורות הנתונים אינו מובטח.

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 היא תהליך דו-שלבי ללקוח אינטרנט. קודם כול היא מפעילה את המאפיין 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 יכול להיווצר על ידי השרת או הלקוח.

לקוחות אינטרנט יכולים ליצור תוכנה כזו באמצעות ה-method 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. הדוגמאות משני הקטעים הקודמים מסבירות כיצד להשתמש בכל אחד מהם.

דוגמאות נוספות

מפרט הטיוטה של WebTransport כולל כמה דוגמאות נוספות מוטבעות, וגם תיעוד מלא של כל השיטות והמאפיינים.

WebTransport בכלי הפיתוח ל-Chrome

לצערנו, כלי הפיתוח של Chrome לא תומכים כרגע ב-WebTransport. אפשר לסמן בכוכב הבעיה הזו ב-Chrome כדי לקבל התראות על עדכונים בממשק של כלי הפיתוח.

פוליפיל

מילוי פוליגון (או ponyfill שמספק פונקציונליות כמודול עצמאי שאפשר להשתמש בו) webtransport-ponyfill-websocket שמטמיעה כמה מהתכונות של WebTransport. חשוב לקרוא בעיון את המגבלות README של הפרויקט כדי לקבוע אם הפתרון הזה יכול להתאים לתרחיש לדוגמה שלכם.

שיקולי פרטיות ואבטחה

לקבלת הנחיות רשמיות, מומלץ לעיין בקטע המתאים במפרט הטיוטה.

משוב

חברי צוות Chrome רוצים לשמוע מה דעתך על ה-API הזה.

משוב על עיצוב ה-API

האם יש משהו ב-API שגוי או לא פועל כצפוי? או שחסרים חלקים שצריך כדי ליישם את הרעיון?

מפרסמים בעיה במאגר GitHub של Web Transport או מוסיפים הערות לגבי בעיה קיימת.

נתקלתם בבעיה בהטמעה?

מצאת באג בהטמעה של Chrome?

דווחו על באג בכתובת https://new.crbug.com. כדאי לכלול כמה שיותר פרטים, וגם הוראות פשוטות לשחזור הקובץ.

אתם מתכננים להשתמש ב-API?

התמיכה הציבורית שלך עוזרת ל-Chrome לתת עדיפות לתכונות, ומראה לספקי דפדפנים אחרים עד כמה חשוב לתמוך בהם.

  • שליחת ציוץ אל @ChromiumDev בעזרת hashtag #WebTransport ופרטים על המיקום ועל אופן השימוש שלך בו.

דיון כללי

אפשר להשתמש בקבוצת Google של web-transport-dev לקבלת שאלות או בעיות כלליות שלא מתאימות לאחת מהקטגוריות האחרות.

אישורים

המאמר הזה משלב מידע מ-WebTransport Explainer, מפרט הטיוטה ומסמכי העיצוב הקשורים. תודה למחברים המתאימים שהעניקו את הבסיס הזה.

התמונה הראשית בפוסט הזה היא של רובין פייר ב-Unbounce.