ฝึก WebRTC ด้วย PeerJS: สร้างเกมเว็บ P2P อย่างง่าย
เผยแพร่แล้ว: 2022-03-11WebRTC เป็นเทคโนโลยีที่ช่วยให้สามารถสื่อสารแบบเรียลไทม์ระหว่างเว็บเบราว์เซอร์ได้ ค่อนข้างใหม่และคำจำกัดความ API ยังถือว่าเป็นแบบร่าง ประกอบกับความจริงที่ว่า WebRTC ยังไม่ได้รับการสนับสนุนจากเว็บเบราว์เซอร์หลัก ๆ ทั้งหมด (และในบรรดาเบราว์เซอร์ที่รองรับ บางตัวไม่รองรับคุณสมบัติทุกอย่างของเทคโนโลยีนี้) ทำให้ค่อนข้างยากที่จะใช้ WebRTC สำหรับแอปพลิเคชันที่สำคัญต่อภารกิจ . หรือคุณจะคิดอย่างนั้น!
นับตั้งแต่เปิดตัวครั้งแรกโดย Google ในเดือนพฤษภาคม 2554 WebRTC ถูกใช้ในเว็บแอปพลิเคชันที่ทันสมัยมากมาย เนื่องจากเป็นคุณสมบัติหลักของเว็บเบราว์เซอร์สมัยใหม่จำนวนมาก เว็บแอปพลิเคชันจึงสามารถใช้ประโยชน์จากเทคโนโลยีนี้ได้อย่างราบรื่นเพื่อมอบประสบการณ์การใช้งานที่ดียิ่งขึ้นแก่ผู้ใช้ในหลาย ๆ ด้าน แอปพลิเคชั่นสตรีมวิดีโอหรือการประชุมที่ไม่ต้องการปลั๊กอินของเบราว์เซอร์ที่บวม และสามารถใช้ประโยชน์จากเครือข่ายเพียร์ทูเพียร์ (P2P) (ในขณะที่ไม่ได้ส่งข้อมูลทุกบิตผ่านเซิร์ฟเวอร์บางตัว) เป็นเพียงส่วนหนึ่งของสิ่งมหัศจรรย์ทั้งหมดที่ สามารถทำได้ด้วย WebRTC
ในบทความนี้ เราจะมาดูกันว่า WebRTC สามารถใช้สร้างเกมเว็บ P2P อย่างง่ายของ Connect Four ได้อย่างไร ในการแก้ไขขอบคร่าวๆ และความแตกต่างในการใช้งาน WebRTC เราจะใช้ไลบรารี JavaScript ที่น่าทึ่ง: PeerJS
ข้อมูลผ่าน WebRTC
ก่อนที่เราจะเริ่ม สิ่งสำคัญคือต้องเข้าใจว่า WebRTC ไม่ได้เกี่ยวกับการส่งสัญญาณเสียงและวิดีโอเท่านั้น นอกจากนี้ยังให้การสนับสนุนช่องข้อมูล P2P ช่องทางเหล่านี้มีสองรูปแบบ: เชื่อถือได้และไม่น่าเชื่อถือ อย่างที่ใครๆ ก็คาดเดา ช่องข้อมูลที่เชื่อถือได้รับประกันว่าข้อความจะถูกส่งและจัดส่งตามลำดับ ในขณะที่ช่องทางที่ไม่น่าเชื่อถือไม่ได้ให้การรับประกันดังกล่าว
นอกจากนี้ ช่องข้อมูล WebRTC ไม่ต้องการการตั้งค่าโครงสร้างพื้นฐานพิเศษ นอกเหนือจากสิ่งที่ต้องการโดยการเชื่อมต่อเพียร์ WebRTC ทั่วไป: เซิร์ฟเวอร์ส่งสัญญาณเพื่อประสานงานการเชื่อมต่อระหว่างเพียร์ เซิร์ฟเวอร์ STUN เพื่อค้นหาเอกลักษณ์สาธารณะของเพียร์ และเซิร์ฟเวอร์ TURN ทางเลือก เพื่อกำหนดเส้นทางข้อความระหว่างเพียร์ หากไม่สามารถสร้างการเชื่อมต่อโดยตรงระหว่างเพียร์ (เช่น เมื่อเพียร์ทั้งสองอยู่เบื้องหลัง NAT) หากคำย่อเหล่านี้ฟังดูคุ้นเคย อาจเป็นเพราะ WebRTC นำเทคโนโลยีที่มีอยู่ไปใช้ใหม่ในทุกที่ที่ทำได้
นี่เป็นการเปิดประตูสู่กรณีการใช้งาน WebRTC จำนวนมากขึ้น ซึ่งรวมถึงแต่ไม่จำกัดเฉพาะเกมที่มีผู้เล่นหลายคน การส่งเนื้อหา และการแชร์ไฟล์ อีกครั้งโดยไม่จำเป็นต้องใช้เซิร์ฟเวอร์ตัวกลางและด้วยเหตุนี้จึงมีเวลาแฝงที่ต่ำกว่า
ในเกมบนเว็บที่เรียบง่ายของเรา เราจะใช้ช่องข้อมูลระหว่างสองเว็บเบราว์เซอร์เพื่อสื่อสารให้ผู้เล่นเคลื่อนที่ไปมา
พบกับ PeerJS
PeerJS นำ WebRTC ไปใช้งานในเบราว์เซอร์ของคุณและรวม API ที่เรียบง่าย สม่ำเสมอ และสวยงามไว้รอบๆ มันอุดช่องโหว่ต่าง ๆ ในการใช้งาน WebRTC ของเบราว์เซอร์รุ่นก่อน ๆ ตัวอย่างเช่น ใน Chrome 30 หรือเก่ากว่า จะมีเฉพาะช่องข้อมูลที่ไม่น่าเชื่อถือเท่านั้น PeerJS หากกำหนดค่าให้ใช้ช่องข้อมูลที่เชื่อถือได้ จะใช้ชิมสำหรับเบราว์เซอร์รุ่นเก่าเหล่านั้น แม้ว่าการดำเนินการนี้จะไม่มีประสิทธิภาพเท่ากับการนำช่องสัญญาณที่เชื่อถือได้ไปใช้ในเครื่อง แต่ก็ยังคงใช้งานได้
ด้วย PeerJS การระบุเพียร์จะง่ายยิ่งขึ้นไปอีก เพียร์ทุกคนจะถูกระบุโดยใช้อะไรนอกจาก ID สตริงที่เพียร์สามารถเลือกเองได้ หรือให้เซิร์ฟเวอร์สร้างไว้ แม้ว่า WebRTC จะสัญญาการสื่อสารแบบเพียร์ทูเพียร์ แต่คุณยังคงต้องการเซิร์ฟเวอร์เพื่อทำหน้าที่เป็นนายหน้าการเชื่อมต่อและจัดการการส่งสัญญาณ PeerJS ให้การใช้งานโอเพ่นซอร์สของเซิร์ฟเวอร์โบรกเกอร์การเชื่อมต่อนี้ เซิร์ฟเวอร์ PeerJS (เขียนใน Node.js) ในกรณีที่คุณไม่ต้องการใช้เวอร์ชันที่โฮสต์บนคลาวด์ (ซึ่งฟรีในขณะนี้ และมาพร้อมกับข้อจำกัดบางประการ)
เชื่อมต่อ Four Goes P2P
ตอนนี้เรามีแหล่งความมั่นใจในการทำงานกับ WebRTC เช่น PeerJS ให้เราเริ่มต้นด้วยการสร้างแอปพลิเคชัน Node.js/Express อย่างง่าย
npm init npm install express --save npm install jade --save npm install peer --saveเราจะใช้สิ่งนี้เพื่อโฮสต์ PeerJS Server และให้บริการเพจและเนื้อหาส่วนหน้าเท่านั้น เราจะต้องให้บริการเพียงหน้าเดียว และจะประกอบด้วยสองส่วน: เมนูหลักธรรมดา และตาราง Connect Four ขนาด 7 คูณ 6
เซิร์ฟเวอร์ PeerJS
การโฮสต์เซิร์ฟเวอร์ PeerJS ของเรานั้นง่ายมาก พื้นที่เก็บข้อมูลอย่างเป็นทางการบน GitHub มีปุ่มเพียงคลิกเดียวเพื่อปรับใช้อินสแตนซ์ของ PeerJS Server กับ Heroku
ในกรณีของเรา เราแค่ต้องการสร้างอินสแตนซ์ของ ExpressPeerServer ในแอปพลิเคชัน Node.js ของเรา และให้บริการที่ “/peerjs”:
var express = require('express') var app = express() // … Configure Express, and register necessary route handlers srv = app.listen(process.env.PORT) app.use('/peerjs', require('peer').ExpressPeerServer(srv, { debug: true }))ไคลเอนต์ PeerJS
เมื่อเปิดใช้งาน PeerJS Server เราจะไปยังฝั่งไคลเอ็นต์ ตามที่กล่าวไว้ก่อนหน้านี้ PeerJS จะระบุเพียร์ที่มี ID เฉพาะ PeerServer สามารถสร้าง ID เหล่านี้ให้กับทุกเพียร์ได้โดยอัตโนมัติ หรือเราจะเลือกหนึ่งรายการสำหรับเพียร์ทุกตัวในขณะที่สร้างอินสแตนซ์ของอ็อบเจ็กต์ Peer
var peer = new Peer(id, options)ที่นี่ สามารถละเว้น id ได้ทั้งหมดหากเราต้องการให้เซิร์ฟเวอร์สร้างรหัสให้เรา ในกรณีของเรา นั่นคือสิ่งที่เราต้องการจะทำ PeerServer จะทำให้แน่ใจว่า ID ที่ให้ออกมานั้นไม่ซ้ำกัน อาร์กิวเมนต์ที่สอง options มักจะเป็นอ็อบเจ็กต์ที่มี คีย์ (คีย์ API หากคุณใช้ PeerServer ที่โฮสต์บนคลาวด์ หรือ host , พอร์ต , เส้นทาง ฯลฯ ในกรณีที่คุณโฮสต์ PeerServer ด้วยตนเอง)
var peer = new Peer({ host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs' })ในการสร้างการเชื่อมต่อระหว่างเพียร์เพียร์สองคน หนึ่งในเพียร์ต้องรู้ ID ของเพียร์อื่น เพื่อประโยชน์ในการทำให้สิ่งต่าง ๆ ง่ายขึ้น ในการใช้งาน Connect Four บน WebRTC เราจะกำหนดให้ผู้เล่นที่เริ่มเกมแชร์ ID เพียร์ของเขากับคู่ต่อสู้ของเขา เมื่อทราบ ID ปลายทางแล้ว การเรียก peer.connect(destId) อย่างง่ายคือสิ่งที่เราต้องการ:

var conn = peer.connect(destId)ทั้งวัตถุ Peer และวัตถุ DataConnection ที่ส่งกลับโดย peer.connect(destId) ได้ ปล่อยเหตุการณ์ที่มีประโยชน์บางอย่างออกมาซึ่งคุ้มค่าที่จะรับฟัง สำหรับจุดประสงค์ของบทช่วยสอนนี้ เราสนใจเป็นพิเศษเกี่ยวกับเหตุการณ์ 'data' ของวัตถุ DataConnection และเหตุการณ์ 'ข้อผิดพลาด' ของทั้งสองวัตถุ
ในการส่งข้อมูลไปยังปลายอีกด้านของการเชื่อมต่อ เพียงแค่เรียกใช้ conn.send(data) :
conn.send('hello')แม้ว่าจะเกินความต้องการของเราเล็กน้อย แต่ PeerJS จะส่งข้อมูลระหว่างเพียร์หลังจากเข้ารหัสในรูปแบบ BinaryPack ซึ่งช่วยให้เพียร์สามารถสื่อสารสตริง ตัวเลข อาร์เรย์ อ็อบเจ็กต์ และแม้แต่ blobs ได้
ในการรับข้อมูลขาเข้า เพียงแค่ฟังเหตุการณ์ 'data' บน conn :
conn.on('data', function(data) { // data === 'hello' })และนั่นคือทั้งหมดที่เราต้องการ!
ตรรกะของเกม
ผู้เล่นคนแรกที่เริ่มเกมจะแสดง ID เพียร์ของเขาซึ่งสร้างโดย PeerJS ซึ่งพวกเขาสามารถแบ่งปันกับคู่ต่อสู้ได้ เมื่อฝ่ายตรงข้ามเข้าร่วมเกมโดยใช้ peer ID ของผู้เล่นคนแรก ผู้เล่นคนแรกจะได้รับอนุญาตให้เคลื่อนไหว
Connect Four เป็นเกมที่มีกฎและกลไกง่าย ๆ มีการเคลื่อนไหวเพียงประเภทเดียว: ผู้เล่นแต่ละคนจะต้องเลือกคอลัมน์แล้ววางแผ่นดิสก์ลงไป ซึ่งหมายความว่าเพียร์ทุกคนต้องการสื่อสารคือหมายเลขคอลัมน์ที่ผู้เล่นปัจจุบันได้เลือกที่จะวางแผ่นดิสก์ของเขา เราจะส่งข้อมูลนี้เป็นอาร์เรย์ที่มีสององค์ประกอบ: สตริง 'ย้าย' และตัวเลข - 0- ดัชนีตามคอลัมน์จากด้านซ้าย
ทุกครั้งที่ผู้เล่นคลิกที่คอลัมน์:
if(!turn) { // it is not the current player's turn return } var i // i = chosen column index if(grid[i].length == 6) { // the column doesn't have any more space available return } // track player's move locally grid[i].push(peerId) // end current player's turn turn = false conn.send(['move', i])หลังจากส่งข้อมูลการเคลื่อนไหวนี้ไปยังฝ่ายตรงข้าม เราจะอัปเดตสถานะของเกมในพื้นที่ ซึ่งรวมถึงการพิจารณาว่าผู้เล่นคนปัจจุบันชนะหรือว่าเกมจบลงด้วยการเสมอกัน
เมื่อสิ้นสุดการรับข้อมูลการย้ายนี้:
if(turn) { // ignore incoming move data when it is the current player's turn return } var i = data[1] if(grid[i].length == 6) { // ignore incoming move data when it is invalid return } // track opponent's move locally grid[i].push(opponent.peerId) // activate current player's turn turn = trueและโดยธรรมชาติ หลังจากนี้ เราจะอัปเดตสถานะของเกมในพื้นที่ พิจารณาว่าคู่ต่อสู้ชนะหรือว่าเกมจบลงด้วยผลเสมอกัน
สังเกตว่าเราจำเป็นต้องดำเนินการตรวจสอบสุขภาพจิตกับข้อมูลที่เข้ามาอย่างไร นี่เป็นสิ่งสำคัญเนื่องจากเกมที่ใช้ WebRTC เราไม่มีเซิร์ฟเวอร์ตัวกลางและตรรกะของเกมบนเซิร์ฟเวอร์ที่ตรวจสอบความถูกต้องของข้อมูลการย้าย
เพื่อให้ข้อมูลโค้ดง่ายขึ้น บรรทัดของโค้ดที่อัปเดต UI ได้ถูกละไว้ คุณสามารถค้นหาซอร์สโค้ดแบบเต็มสำหรับ JavaScript ฝั่งไคลเอ็นต์ได้ที่นี่
เชื่อมต่อทุกอย่าง
เพื่อรวมทุกอย่างเข้าด้วยกัน เราสร้างหน้าง่ายๆ ที่มีสองส่วน ในการโหลดหน้า ส่วนที่มีเมนูหลักจะปรากฏขึ้น ส่วนที่มีตารางเกมจะถูกซ่อนไว้
section#menu div.animated.bounceIn div h1 Connect Four br div.no-support() div.alert.alert-warning p Unfortunately, your web browser does not <a href="http://iswebrtcreadyyet.com">support WebRTC</a> div a.btn.btn-primary.btn-lg(href='#start') Start | a.btn.btn-default.btn-lg(href='#join') Join section#game() div div h1 Connect Four br table.table.grid tbody for i in [0, 1, 2, 3, 4, 5] tr for j in [0, 1, 2, 3, 4, 5, 6] td div.slot br div.alert.alert-info pการทำให้องค์ประกอบ DOM เหล่านี้ดูสวยงามนั้นอยู่นอกเหนือขอบเขตของบทช่วยสอนนี้ ดังนั้นเราจะหันไปใช้ Bootstrap ที่ไว้ใจได้ของเราและจัดสไตล์เบา ๆ ทับมัน
เมื่อผู้เล่นคนแรกคลิกที่ปุ่ม "เริ่ม" ตารางเกมจะแสดงพร้อมกับรหัสเพียร์ของผู้เล่น ผู้เล่นสามารถแชร์ ID เพียร์นี้กับคู่ต่อสู้ของตนได้
ผู้เล่นคนที่สองสามารถคลิกจากนั้นคลิกที่ปุ่ม “เข้าร่วม” ป้อน ID เพียร์ของผู้เล่นคนแรก และเริ่มเกม
ลองเลย
คุณสามารถลองใช้แอปพลิเคชันตัวอย่างนี้ได้ที่ https://arteegee.herokuapp.com
หรือคุณสามารถโคลนที่เก็บจาก GitHub ติดตั้งการพึ่งพา NPM และลองใช้ในเครื่อง:
git clone https://github.com/hjr265/arteegee.git cd arteegee npm install PORT=5000 npm startเมื่อเซิร์ฟเวอร์ทำงาน คุณสามารถชี้เว็บเบราว์เซอร์ของคุณไปที่ http://localhost:5000 เริ่มเกมจากแท็บหนึ่ง และเข้าร่วมจากแท็บอื่น (หรือแม้แต่เว็บเบราว์เซอร์ที่มีความสามารถ WebRTC อื่น) โดยใช้รหัสเพียร์
คุณสามารถเปิดคอนโซลของเว็บเบราว์เซอร์เพื่อดูข้อมูลการดีบักบางอย่างได้ เช่นเดียวกับในแอปพลิเคชันตัวอย่างนี้ ไคลเอ็นต์ PeerJS ได้รับการกำหนดค่าให้ทำการบันทึกแบบละเอียด
แต่มันใช้ไม่ได้สำหรับฉัน!
มีเหตุผลหลักสองประการที่ทำให้เกมนี้ใช้งานไม่ได้บนคอมพิวเตอร์ของคุณ
เป็นไปได้ว่าคุณกำลังใช้เว็บเบราว์เซอร์ที่ยังไม่รองรับ WebRTC API ที่จำเป็น หากเป็นกรณีนี้ คุณอาจต้องการลองใช้เบราว์เซอร์อื่น ซึ่งสนับสนุน WebRTC และช่องข้อมูล
หากคุณกำลังใช้เว็บเบราว์เซอร์สมัยใหม่ที่รองรับ WebRTC มีโอกาสที่คุณจะอยู่เบื้องหลังโครงสร้างพื้นฐานเครือข่ายบางอย่างที่ WebRTC ไม่สามารถเจาะได้ ตามหลักการแล้ว ปัญหานี้สามารถแก้ไขได้ง่ายๆ ด้วยเซิร์ฟเวอร์ TURN แต่เนื่องจากแอปพลิเคชันตัวอย่างไม่ได้ใช้ จึงไม่สามารถใช้งานได้เมื่อทั้งคุณและคู่ต่อสู้ของคุณอยู่เบื้องหลัง NAT
บทสรุป
WebRTC เป็นเทคโนโลยีใหม่และการใช้งานนั้นยังห่างไกลจากการพัฒนา สิ่งเหล่านี้มักทำให้เกิดความท้าทายที่ไม่เหมือนใครสำหรับนักพัฒนา อย่างไรก็ตาม ด้วยความพร้อมใช้งานของไลบรารีอย่าง PeerJS ที่แยก API ดิบคร่าวๆ ออกไปอย่างเรียบร้อย เทคโนโลยีจึงเข้าถึงได้ค่อนข้างดีอยู่แล้ว
ฉันหวังว่าบทช่วยสอนสั้นๆ นี้สำหรับการสร้างเกมที่ใช้ PeerJS จะช่วยให้คุณเริ่มต้นกับ WebRTC และสร้างแอปพลิเคชันเว็บเพียร์ทูเพียร์แบบเรียลไทม์ที่น่าทึ่ง
