ส่งข้อมูลระหว่างเบราว์เซอร์ที่มีแชแนลข้อมูล WebRTC

Dan Ristic
ความสัมพันธ์กับเดนมาร์ก

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

ปัญหาเหล่านี้บรรเทาได้โดยใช้ RTCDataChannel API ของ WebRTC เพื่อโอนข้อมูลจากเครื่องหนึ่งไปยังอีกเครื่องหนึ่งโดยตรง บทความนี้ครอบคลุมพื้นฐานวิธีตั้งค่าและใช้ช่องทางข้อมูล รวมถึงกรณีการใช้งานทั่วไปบนเว็บในปัจจุบัน

สาเหตุที่ควรใช้ช่องทางข้อมูลอื่น

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

RTCDataChannel ใช้วิธีอื่น

  • ฟีเจอร์นี้ใช้งานได้กับ RTCPeerConnection API ซึ่งช่วยให้เชื่อมต่อแบบเพียร์ทูเพียร์ได้ ซึ่งอาจส่งผลให้เวลาในการตอบสนองต่ำลง - ไม่มีเซิร์ฟเวอร์ตัวกลาง และมี "รอบ" น้อยลง
  • RTCDataChannel ใช้ Stream Control TExport Protocol (SCTP) ช่วยให้นำส่งการกำหนดค่าการนำส่งนอกการสั่งซื้อได้และนำส่งการกำหนดค่าได้

RTCDataChannel พร้อมให้บริการแล้วด้วยการรองรับ SCTP ในเดสก์ท็อปและ Android ใน Google Chrome, Opera และ Firefox

ข้อควรระวัง: การส่งสัญญาณ, STUN และ TURN

WebRTC เปิดใช้การสื่อสารแบบเพียร์ทูเพียร์ แต่ยังต้องการเซิร์ฟเวอร์สำหรับการส่งสัญญาณเพื่อแลกเปลี่ยนสื่อและข้อมูลเมตาของเครือข่ายเพื่อเปิดการเชื่อมต่อแบบเพียร์

WebRTC จะทำงานร่วมกับ NAT และไฟร์วอลล์ด้วยสิ่งต่อไปนี้

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

โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ WebRTC ทำงานร่วมกับเซิร์ฟเวอร์สำหรับการส่งสัญญาณและการสร้างเครือข่ายที่หัวข้อ WebRTC ในชีวิตจริง: STUN, TURN และการส่งสัญญาณ

ความสามารถ

RTCDataChannel API รองรับชุดข้อมูลประเภทที่ยืดหยุ่น API นี้ออกแบบมาให้เลียนแบบ WebSocket ทุกประการ และ RTCDataChannel รองรับสตริง รวมถึงไบนารีบางประเภทใน JavaScript เช่น Blob, ArrayBuffer และ ArrayBufferView ประเภทดังกล่าวจะมีประโยชน์เมื่อต้องโอนไฟล์และเล่นเกมแบบผู้เล่นหลายคน

RTCDataChannel อาจทำงานในโหมดที่ไม่น่าเชื่อถือและไม่มีลำดับ (คล้ายกับโปรโตคอล User Datagram หรือ UDP), โหมดที่เชื่อถือได้และสั่งซื้อ (คล้ายกับ TExport Control Protocol หรือ TCP) และโหมดที่เชื่อถือได้บางส่วน ดังนี้

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

ประสิทธิภาพของ 2 โหมดแรกจะเท่ากันเมื่อไม่สูญเสียแพ็กเก็ต อย่างไรก็ตาม ในโหมดที่เสถียรและสั่งซื้อได้ แพ็กเก็ตที่สูญหายจะทำให้แพ็กเก็ตอื่นๆ ตามหลังแพ็กเก็ตนั้นหายไป และแพ็กเก็ตที่สูญหายอาจไม่อัปเดตเมื่อมีการส่งแพ็กเก็ตอีกครั้งและมาถึงแล้ว แน่นอนว่ามีความเป็นไปได้ในการใช้ช่องทางข้อมูลหลายๆ ช่องทางภายในแอปเดียวกัน โดยแต่ละช่องทางมีความหมายที่เชื่อถือได้หรือเชื่อถือไม่ได้

ตารางที่เป็นประโยชน์จากเครือข่ายเบราว์เซอร์ประสิทธิภาพสูงโดย Ilya Grigorik

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 ดูข้อมูลเพิ่มเติมได้ที่ IETF RFCs ต่อไปนี้ Stream Control Tunction Protocol และ Stream Control TExport Protocol Fully Reliability Extension

  • ordered: ช่องทางข้อมูลควรรับประกันการสั่งซื้อหรือไม่
  • maxPacketLifeTime: เวลาสูงสุดในการพยายามส่งข้อความที่ล้มเหลวอีกครั้ง
  • maxRetransmits: จำนวนครั้งสูงสุดในการพยายามส่งข้อความที่ล้มเหลวอีกครั้ง
  • protocol: อนุญาตให้ใช้โปรโตคอลย่อยที่ระบุข้อมูลเมตาเกี่ยวกับแอป
  • negotiated: หากตั้งค่าเป็น "จริง" จะนำการตั้งค่าอัตโนมัติของช่องทางข้อมูลในอีกเครือข่ายหนึ่งออกเพื่อกำหนดช่องทางข้อมูลของคุณเองด้วยรหัสเดียวกันในอีกฝั่งหนึ่ง
  • id: ให้คุณระบุรหัสของคุณเองสำหรับช่องซึ่งสามารถใช้ร่วมกับ negotiated ที่ตั้งค่าเป็น true เท่านั้น)

ตัวเลือกเดียวที่ผู้คนส่วนใหญ่ต้องใช้คือ 3 ตัวเลือกแรก ได้แก่ ordered, maxPacketLifeTime และ maxRetransmits เมื่อมี SCTP (ขณะนี้ใช้โดยเบราว์เซอร์ทั้งหมดที่รองรับ WebRTC) เชื่อถือได้และมีการสั่งซื้อเป็น "จริง" โดยค่าเริ่มต้น คุณควรใช้ความเสถียรและไม่เรียงลำดับหากต้องการการควบคุมจากเลเยอร์แอปอย่างเต็มที่ แต่ในกรณีส่วนใหญ่ ความเสถียรบางส่วนจะเป็นประโยชน์

โปรดทราบว่า เช่นเดียวกับ WebSocket RTCDataChannel จะเริ่มเหตุการณ์เมื่อมีการสร้างการเชื่อมต่อ ปิด หรือเกิดข้อผิดพลาด และเมื่อได้รับข้อความจากเพียร์อื่น เช่นเดียวกับ WebSocket

เทรนด์หรือชาเลนจ์นี้ปลอดภัยไหม

คอมโพเนนต์ WebRTC ทั้งหมดจำเป็นต้องมีการเข้ารหัส เมื่อใช้ RTCDataChannel ข้อมูลทั้งหมดจะปลอดภัยด้วย Datagram Transport Layer Security (DTLS) DTLS เป็นอนุพันธ์ของ SSL ซึ่งหมายความว่าข้อมูลของคุณจะมีความปลอดภัยเหมือนกับการใช้การเชื่อมต่อแบบ SSL มาตรฐาน DTLS ได้รับมาตรฐานและมีอยู่ในเบราว์เซอร์ทั้งหมดที่รองรับ WebRTC ดูข้อมูลเพิ่มเติมได้ใน Wireshark wiki

เปลี่ยนวิธีคิดเกี่ยวกับข้อมูล

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

สร้างแอปสำหรับแชร์ไฟล์

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

การดำเนินการโอนสำเร็จมีดังนี้

  1. อ่านไฟล์ใน JavaScript โดยใช้ File API
  2. เชื่อมต่อแบบเพียร์ระหว่างไคลเอ็นต์ด้วย RTCPeerConnection
  3. สร้างแชแนลข้อมูลระหว่างไคลเอ็นต์ด้วย RTCDataChannel

สิ่งที่ควรพิจารณาเมื่อพยายามส่งไฟล์เกิน RTCDataChannel มีดังนี้

  • ขนาดไฟล์: หากไฟล์มีขนาดเล็กพอสมควรและสามารถจัดเก็บและโหลดเป็น Blob เดียวได้ คุณสามารถโหลดลงในหน่วยความจำโดยใช้ File API แล้วส่งไฟล์ไปยังช่องทางที่เชื่อถือได้ตามที่เป็นอยู่ (แต่โปรดทราบว่าเบราว์เซอร์จะกำหนดขีดจำกัดขนาดการโอนสูงสุด) เมื่อไฟล์มีขนาดใหญ่ขึ้น สิ่งต่างๆ ก็จะซับซ้อนขึ้น เมื่อต้องใช้กลไกการแบ่งส่วน ระบบจะโหลดชิ้นส่วนไฟล์และส่งไปยังเพียร์รายอื่น พร้อมด้วยข้อมูลเมตา chunkID เพื่อให้เพียร์จดจำได้ โปรดทราบว่าในกรณีนี้ คุณจะต้องบันทึกส่วนดังกล่าวลงในพื้นที่เก็บข้อมูลออฟไลน์ก่อน (เช่น การใช้ FileSystem API) แล้วบันทึกลงในดิสก์ของผู้ใช้ต่อเมื่อคุณมีไฟล์ครบถ้วนเท่านั้น
  • ขนาดกลุ่ม: ข้อมูลเหล่านี้คือ "ขนาดเล็ก" ที่เล็กที่สุดสำหรับแอปของคุณ คุณจำเป็นต้องแบ่งเป็นส่วนย่อยๆ เนื่องจากขณะนี้มีการจำกัดขนาดการส่ง (แต่จะแก้ไขในแชแนลข้อมูลเวอร์ชันในอนาคต) คำแนะนำปัจจุบันสำหรับขนาดกลุ่มสูงสุดคือ 64 KiB

เมื่อโอนไฟล์ไปยังอีกฝั่งหนึ่งเสร็จสมบูรณ์แล้ว คุณจะดาวน์โหลดไฟล์ได้โดยใช้แท็ก Anchor ดังนี้

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 ซึ่งเป็นเฟรมเวิร์กที่ส่งเนื้อหาเว็บผ่านการสื่อสารข้อมูลแบบเพียร์ทูเพียร์

เปลี่ยนวิธีสร้างแอป

ตอนนี้คุณให้บริการแอปที่น่าสนใจมากขึ้นได้แล้วโดยใช้การเชื่อมต่อประสิทธิภาพสูงและเวลาในการตอบสนองต่ำผ่าน RTCDataChannel เฟรมเวิร์ก เช่น PeerJS และ PubNub WebRTC SDK ช่วยให้ RTCDataChannel ติดตั้งใช้งานได้ง่ายขึ้น นอกจากนี้ API ยังรองรับการใช้งานในวงกว้างบนแพลตฟอร์มต่างๆ

การถือกำเนิดของ RTCDataChannel อาจเปลี่ยนมุมมองที่คุณมีต่อการโอนข้อมูลในเบราว์เซอร์

ดูข้อมูลเพิ่มเติม