שליחת נתונים בין דפדפנים עם ערוצי נתונים WebRTC

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

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

למה כדאי להשתמש בערוץ נתונים נוסף?

יש לנו את WebSocket, AJAX ואירוע שנשלח על ידי שרת. למה אנחנו צריכים ערוץ תקשורת נוסף? WebSocket הוא דו-כיווני, אבל כל הטכנולוגיות האלה מיועדות לתקשורת לשרת או ממנו.

RTCDataChannel נוקטת גישה שונה:

  • הוא פועל עם ממשק ה-API של RTCPeerConnection, שמאפשר קישוריות מקצה לקצה (P2P). התוצאה עשויה להיות זמן אחזור קצר יותר – ללא שרת ביניים ופחות 'צעדים'.
  • ב-RTCDataChannel נעשה שימוש ב-Stream Control Transmission Protocol (SCTP), שמאפשר להגדיר סמנטיקה של מסירה שלא לפי הסדר והגדרה של שידור מחדש.

RTCDataChannel זמין עכשיו עם תמיכה ב-SCTP במחשבים שולחניים ובמכשירי Android ב-Google Chrome, Opera ו-Firefox.

אזהרה: איתות, STUN ו-TURN

WebRTC מאפשר תקשורת מקצה לקצה, אבל עדיין צריך שרתים כדי לאות כדי להחליף מדיה ומטא-נתונים של הרשת כדי לאתחל חיבור בין רשתות שכנות.

WebRTC מתמודד עם NAT וחומות אש עם:

  • מסגרת ה-ICE לקביעת נתיב הרשת הטוב ביותר בין העמיתים.
  • שרתי STUN לבדיקת כתובת IP ויציאה נגישים לציבור לכל אפליקציה להשוואה.
  • מומלץ להפעיל שרתים אם החיבור הישיר נכשל ונדרשת העברת נתונים.

למידע נוסף על האופן שבו WebRTC פועל עם שרתים לאיתות ורשתות, ניתן לעיין במאמר WebRTC בעולם האמיתי: STUN, TURN ואותות.

היכולות

ממשק ה-API של RTCDataChannel תומך בקבוצה גמישה של סוגי נתונים. ממשק ה-API נועד לחקות את WebSocket בדיוק, ו-RTCDataChannel תומך במחרוזות ובחלק מהסוגים הבינאריים ב-JavaScript, כמו Blob , ArrayBuffer ו-ArrayBufferView. הסוגים האלה יכולים להיות שימושיים כשעובדים עם העברת קבצים ומשחקים רבי-משתתפים.

RTCDataChannel יכול לפעול במצב לא אמין ולא מסודר (דומה לפרוטוקול User Datagram או UDP), במצב אמין ומסודר (דומה ל-Transmission Control Protocol או TCP) ובמצבים אמינים חלקיים:

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

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

הנה טבלה שימושית מ-High Performance Browser Networking מאת Ilya Graigorik:

TCPUDPSCTP
אמינותאמיןהמידע לא אמיןניתן להגדיר
משלוחהזמנה שלללא סדרניתן להגדיר
שידורמוכוון בייטיםמוכוון מסרמוכוון מסר
בקרת זרימהכןלאכן
מניעת עומסכןלאכן

בשלב הבא, נסביר איך להגדיר את RTCDataChannel לשימוש במצב אמין, מסודר או לא אמין ולא לפי סדר.

הגדרת ערוצי נתונים

יש כמה הדגמות פשוטות של RTCDataChannel באינטרנט:

בדוגמאות האלה, הדפדפן יוצר חיבור עמית לעצמו, ואז יוצר ערוץ נתונים ושולח הודעה דרך החיבור השכן. לאחר מכן המערכת יוצרת ערוץ נתונים ושולחת את ההודעה דרך החיבור של האפליקציה להשוואה. לבסוף, ההודעה שלך תופיע בתיבה שבצד השני של הדף!

הקוד שיעזור לכם להתחיל הוא קצר:

const peerConnection = new RTCPeerConnection();

// Establish your peer connection using your signaling channel here
const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};

האובייקט dataChannel נוצר מחיבור בין רשתות שכנות שכבר קיים. אפשר ליצור אותו לפני או אחרי תחילת האות. לאחר מכן מעבירים תווית כדי להבדיל בין הערוץ הזה לבין ערוצים אחרים, וקובעים הגדרות אופציונליות:

const dataChannelOptions = {
  ordered: false, // do not guarantee order
  maxPacketLifeTime: 3000, // in milliseconds
};

אפשר גם להוסיף אפשרות maxRetransmits (מספר הפעמים שיש לנסות לפני הכשל), אבל אפשר לציין רק maxRetransmits או maxPacketLifeTime, ולא את שניהם. לסמנטיקה של UDP, מגדירים את maxRetransmits לערך 0 ואת ordered כ-false. למידע נוסף, עיינו במסמכי ה-RFC של IETF הבאים: פרוטוקול השידור לבקרת שידור ותוסף אמינות חלקית של פרוטוקול שידור בקרת שידור.

  • ordered: אם ערוץ הנתונים אמור להבטיח הזמנה או לא
  • maxPacketLifeTime: משך הזמן המקסימלי לניסיון ולשליחת הודעה שנכשלה
  • maxRetransmits: מספר הפעמים המקסימלי שמנסים להעביר הודעה שנכשלה
  • protocol: מאפשר להשתמש בפרוטוקול משנה שמספק מטא מידע לגבי האפליקציה
  • negotiated: אם המדיניות מוגדרת כ-True, ההגדרה האוטומטית של ערוץ נתונים תוסר אצל אפליקציה להשוואה, וכך תספקו דרך משלכם ליצירת ערוץ נתונים עם אותו מזהה בצד השני
  • id: מאפשרת לספק תעודה מזהה משלך לערוץ שניתן להשתמש בו רק בשילוב עם negotiated שמוגדר ל-true)

האפשרויות היחידות שבהן רוב האנשים צריכים להשתמש הן שלוש האפשרויות הראשונות: ordered, maxPacketLifeTime ו-maxRetransmits. באמצעות SCTP (בשימוש עכשיו כל הדפדפנים שתומכים ב-WebRTC) אפשר להציג בצורה אמינה ומסודרת כ-true כברירת מחדל. כדאי להשתמש באמינות ולא מסודרות אם רוצים להשיג שליטה מלאה משכבת האפליקציה, אבל ברוב המקרים, אמינות חלקית מועילה.

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

זה בטוח?

חובה להצפין את כל רכיבי WebRTC. באמצעות RTCDataChannel, כל הנתונים מאובטחים באמצעות Datagram Transport Layer Security (DTLS). DTLS הוא נגזר של SSL, כלומר הנתונים שלך יהיו מאובטחים כמו בכל חיבור סטנדרטי מבוסס SSL. DTLS הוא סטנדרטי ומובנה בכל הדפדפנים שתומכים ב-WebRTC. למידע נוסף, ראה וויקי של Wireshark.

שינוי אופן החשיבה על נתונים

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

בניית אפליקציה לשיתוף קבצים

עכשיו אפשר ליצור אפליקציית אינטרנט שיכולה לשתף קבצים בדפדפן באמצעות RTCDataChannel. המשמעות של מבנה על גבי RTCDataChannel היא שנתוני הקובץ שהועברו מוצפנים ולא נוגעים בשרתים של ספק אפליקציות. הפונקציונליות הזו, בשילוב עם האפשרות להתחבר ללקוחות מרובים לצורך שיתוף מהיר יותר, הופכים את שיתוף קובצי WebRTC למועמד חזק באינטרנט.

יש כמה שלבים שצריך לבצע כדי לבצע העברה בהצלחה:

  1. ניתן לקרוא קובץ ב-JavaScript באמצעות File API.
  2. יצירת חיבור עמית בין לקוחות באמצעות RTCPeerConnection.
  3. כדאי ליצור ערוץ נתונים בין לקוחות עם RTCDataChannel.

יש כמה נקודות שכדאי להביא בחשבון כשמנסים לשלוח קבצים בכמות גדולה מ-RTCDataChannel:

  • גודל הקובץ: אם גודל הקובץ קטן במידה סבירה וניתן לאחסן ולטעון אותו כ-Blob אחד, אפשר לטעון אותו לזיכרון באמצעות File API ואז לשלוח את הקובץ בערוץ מהימן כפי שהוא (עם זאת, חשוב לזכור שהדפדפנים מטילים מגבלות על גודל ההעברה המקסימלי). ככל שגודל הקובץ גדל, כך הדברים נעשים מסובכים יותר. כשנדרש מנגנון כיווץ קבצים, מקטעי קבצים נטענים ונשלחים לעמית אחר, בצירוף המטא-נתונים של chunkID, כדי שהעמית יוכל לזהות אותם. חשוב לשים לב שבמקרה הזה צריך גם לשמור קודם את המקטעים באחסון אופליין (למשל באמצעות FileSystem API) ולשמור אותם בדיסק של המשתמש רק אם הקובץ בשלמותו נמצא.
  • גודל קבוצת הנתונים: אלה ה "קטמים" הקטנים ביותר של נתוני האפליקציה. צריך לבצע קיבוץ כי קיימת מגבלת גודל שליחה (אבל היא תתוקן בגרסה עתידית של ערוצי נתונים). ההמלצה הנוכחית לגודל המקטע המקסימלי היא 64KiB.

לאחר שהקובץ הועבר במלואו לצד השני, ניתן יהיה להוריד אותו באמצעות תג עוגן:

function saveFile(blob) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

זו השיטה שבה משתמשים באפליקציות לשיתוף קבצים ב-PubShare וב-GitHub. הן גם מבוססות על קוד פתוח וגם מספקות בסיס טוב לאפליקציה לשיתוף קבצים שמבוססת על RTCDataChannel.

אז מה אתם יכולים לעשות?

RTCDataChannel פותח דלתות לדרכים חדשות לבנות אפליקציות לשיתוף קבצים, למשחקים רבי-משתתפים ולהעברת תוכן.

  • שיתוף קבצים מקצה לקצה כפי שתואר קודם
  • משחקים מרובי-משתתפים, בשילוב עם טכנולוגיות אחרות, כמו WebGL, כפי שהן מופיעות ב-BananaBread של Mozilla
  • העברת תוכן דומה להמציא מחדש של PeerCDN, מסגרת שמספקת נכסי אינטרנט באמצעות תקשורת נתונים מקצה לקצה (P2P)

שינוי אופן הבנייה של אפליקציות

עכשיו אפשר לספק אפליקציות מעניינות יותר באמצעות חיבורים עם זמן אחזור קצר וביצועים גבוהים באמצעות RTCDataChannel. מסגרות כמו PeerJS ו-PubNub WebRTC SDK מאפשרים להטמיע את RTCDataChannel בקלות, ול-API יש עכשיו תמיכה רחבה בפלטפורמות שונות.

ההופעה של RTCDataChannel יכולה לשנות את הדרך שבה אתה חושב על העברת נתונים בדפדפן.

למידע נוסף