การส่งข้อมูลระหว่างเบราว์เซอร์ 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 ช่วยให้การสื่อสารแบบ Peer-to-Peer เป็นไปได้ แต่ยังคงต้องใช้เซิร์ฟเวอร์สำหรับการส่งสัญญาณเพื่อแลกเปลี่ยนข้อมูลเมตาของสื่อและเครือข่ายเพื่อเริ่มต้นการเชื่อมต่อแบบ Peer
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 มีดังนี้
TCP | UDP | SCTP | |
ความน่าเชื่อถือ | เชื่อถือได้ | ไม่น่าเชื่อถือ | กำหนดค่าได้ |
บริการจัดส่ง | ตามลำดับ | ไม่ได้จัดเรียง | กำหนดค่าได้ |
ชุดเกียร์ | มุ่งเน้นไบต์ | เน้นข้อความ | เน้นข้อความ |
การควบคุมโฟลว์ | ใช่ | ไม่ได้ | ใช่ |
การควบคุมการจราจร | ใช่ | ไม่ได้ | ใช่ |
ถัดไป คุณจะได้ดูวิธีกำหนดค่า 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 เป็นตัวเลือกที่น่าสนใจสำหรับเว็บ
คุณต้องทําตามขั้นตอนต่อไปนี้เพื่อให้การโอนสําเร็จ
- อ่านไฟล์ใน JavaScript โดยใช้ File API
- สร้างการเชื่อมต่อแบบ Peer ระหว่างไคลเอ็นต์ด้วย
RTCPeerConnection
- สร้างช่องทางข้อมูลระหว่างไคลเอ็นต์ด้วย
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
จะช่วยให้คุณเปลี่ยนมุมมองเกี่ยวกับการโอนข้อมูลในเบราว์เซอร์ได้