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

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

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

เหตุใดจึงต้องมีช่องทางข้อมูลอีกช่องทางหนึ่ง

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

RTCDataChannel ใช้แนวทางที่ต่างออกไป ดังนี้

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

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

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

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

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

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

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

ความสามารถ

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

RTCDataChannel สามารถทํางานในโหมดที่ไม่เสถียรและไม่เป็นระเบียบ (คล้ายกับ User Datagram Protocol หรือ UDP) โหมดที่เสถียรและเป็นระเบียบ (คล้ายกับ Transmission Control Protocol หรือ TCP) และโหมดที่เสถียรบางส่วน ดังนี้

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

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

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

TCPUDPSCTP
ความน่าเชื่อถือเชื่อถือได้ไม่น่าเชื่อถือกำหนดค่าได้
บริการจัดส่งตามลำดับไม่เรียงลำดับกำหนดค่าได้
ชุดเกียร์มุ่งเน้นที่ไบต์เน้นข้อความเน้นข้อความ
การควบคุมโฟลว์ใช่ไม่ได้ใช่
การควบคุมการจราจรใช่ไม่ได้ใช่

ถัดไป คุณจะได้ดูวิธีกำหนดค่า RTCDataChannel ให้ใช้โหมดที่เชื่อถือได้และมีลําดับหรือโหมดที่ไม่น่าเชื่อถือและไม่มีลําดับ

การกำหนดค่าแชแนลข้อมูล

คุณสามารถดูการสาธิต RTCDataChannel ง่ายๆ หลายรายการทางออนไลน์ได้ ดังนี้

ในตัวอย่างเหล่านี้ เบราว์เซอร์จะสร้างการเชื่อมต่อแบบ Peer กับตัวเอง จากนั้นสร้างแชแนลข้อมูลและส่งข้อความผ่านการเชื่อมต่อแบบ Peer จากนั้นจะสร้างช่องทางข้อมูลและส่งข้อความไปตามการเชื่อมต่อแบบ Peer สุดท้าย ข้อความของคุณจะปรากฏในช่องอีกฝั่งหนึ่งของหน้า

โค้ดสั้นๆ สำหรับการเริ่มต้นใช้งานมีดังนี้

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 สร้างขึ้นจากการเชื่อมต่อแบบ Peer ที่สร้างขึ้นแล้ว โดยอาจสร้างขึ้นก่อนหรือหลังการส่งสัญญาณ จากนั้นส่งป้ายกํากับเพื่อแยกช่องนี้ออกจากช่องอื่นๆ และชุดการตั้งค่าการกําหนดค่าที่ไม่บังคับ

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

นอกจากนี้ คุณยังเพิ่มตัวเลือก maxRetransmits (จำนวนครั้งที่จะลองส่งก่อนที่จะไม่สำเร็จ) ได้ แต่คุณจะระบุได้เพียง maxRetransmits หรือ maxPacketLifeTime เท่านั้น สำหรับความหมายของ UDP ให้ตั้งค่า maxRetransmits เป็น 0 และ ordered เป็น false ดูข้อมูลเพิ่มเติมได้ที่ RFC ของ IETF ต่อไปนี้ Stream Control Transmission Protocol และ Stream Control Transmission Protocol Partial Reliability Extension

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

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

โปรดทราบว่า 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. สร้างการเชื่อมต่อแบบ Peer ระหว่างไคลเอ็นต์ด้วย 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 ใช้เทคนิคนี้ โดยทั้ง 2 แพลตฟอร์มนี้เป็นโอเพนซอร์สและเป็นรากฐานที่ดีสําหรับแอปการแชร์ไฟล์ที่อิงตาม RTCDataChannel

คุณทำอะไรได้บ้าง

RTCDataChannel เปิดโอกาสให้สร้างแอปใหม่ๆ สำหรับการแชร์ไฟล์ เกมแบบหลายผู้เล่น และการส่งเนื้อหา

  • การแชร์ไฟล์แบบเพียร์ทูเพียร์ตามที่อธิบายไว้ก่อนหน้านี้
  • การเล่นเกมแบบผู้เล่นหลายคนที่จับคู่กับเทคโนโลยีอื่นๆ เช่น WebGL ดังที่เห็นใน BananaBread ของ Mozilla
  • PeerCDN กำลังคิดค้นวิธีใหม่ในการแสดงเนื้อหา ซึ่งเป็นเฟรมเวิร์กที่ใช้การสื่อสารข้อมูลแบบ Peer-to-Peer เพื่อนำส่งชิ้นงานบนเว็บ

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

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

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

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