本文概述
WebRTC是一种启用Web浏览器之间实时通信的技术。它相对较新, 并且API定义仍被视为草稿。再加上所有主要的网络浏览器尚未支持WebRTC(并且其中一些浏览器不支持该技术的所有功能), 这使得将WebRTC用于任何关键任务应用程序相对比较困难。 。否则, 你会认为!
使用PeerJS在WebRTC上连接四人:看, 没有服务器!
鸣叫
自Google于2011年5月首次推出以来, WebRTC已在许多现代Web应用程序中使用。作为许多现代Web浏览器的核心功能, Web应用程序可以无缝地利用此技术, 以多种方式提供改善的用户体验。视频流或会议应用程序不需要庞大的浏览器插件, 并且可以利用对等(P2P)网络(而不会通过服务器传输所有数据)只是所有令人惊奇的事情的一部分可以使用WebRTC实现。
在本文中, 我们将研究如何使用WebRTC制作一个简单的Connect Four P2P网络游戏。为了解决WebRTC的各种粗糙之处和实现差异, 我们将使用一个令人惊叹的JavaScript库:PeerJS。
WebRTC上的数据
在开始之前, 重要的是要了解WebRTC不仅涉及传输音频和视频流。它还提供对P2P数据通道的支持。这些渠道有两种变化:可靠和不可靠。就像人们可能猜到的那样, 可靠的数据通道可确保传递消息并按顺序传递消息, 而不可靠的通道则不提供此类保证。
WebRTC基础结构-缩略语的海洋
鸣叫
此外, 除了典型的WebRTC对等连接所需要的之外, WebRTC数据通道不需要特殊的基础结构设置:用于协调对等体之间连接的信令服务器, 用于确定对等体公共身份的STUN服务器以及可选的TURN服务器如果无法在对等体之间建立直接连接(例如, 当两个对等体都位于NAT之后), 则在对等体之间路由消息。如果这些首字母缩写听起来很熟悉, 那是因为WebRTC尽可能地重新利用了现有技术。
这为WebRTC的更多使用案例打开了大门, 包括但不限于多人游戏, 内容交付和文件共享。同样, 所有这些都不需要任何中间服务器, 因此延迟更短。
在我们简单的网络游戏中, 我们将使用两个网络浏览器之间的数据通道来交流玩家的来回移动。
认识PeerJS
PeerJS在你的浏览器中实现WebRTC的实现, 并在其周围包装了一个简单, 一致且优雅的API。它填补了早期浏览器的WebRTC实施中的各种漏洞。例如, 在Chrome 30或更旧的版本中, 只有不可靠的数据通道可用。如果将PeerJS配置为使用可靠的数据通道, 则将对那些较旧的浏览器使用填充程序。尽管这不像可靠渠道的本机实施那样出色, 但仍然可以使用。
使用PeerJS, 识别对等节点甚至更加简单。仅使用ID来标识每个对等方。对等方可以自行选择或由服务器生成的字符串。尽管WebRTC承诺了对等通信, 但无论如何你仍然需要服务器充当连接代理并处理信令。如果你不想使用它们的云托管版本(目前是免费的, 并且有一些限制), PeerJS提供了此连接代理服务器PeerJS Server(用Node.js编写)的开源实现。
连接四通P2P
现在我们有了使用WebRTC的信心, 即PeerJS, 让我们从创建一个简单的Node.js / Express应用程序开始。
npm init
npm install express --save
npm install jade --save
npm install peer --save
我们将仅使用它来托管PeerJS Server, 并提供页面和前端资产。我们只需要提供一个页面, 该页面将包含两个部分:一个简单的主菜单和一个7×6的”连接四个”网格。
PeerJS服务器
托管我们自己的PeerJS Server非常容易。 GitHub上的官方存储库甚至具有一键式按钮, 可将PeerJS Server实例部署到Heroku。
在我们的例子中, 我们只想在Node.js应用程序中创建ExpressPeerServer的实例, 并将其提供给” / 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的对等体。这些ID可以由PeerServer为每个对等体自动生成, 或者我们可以在实例化Peer对象时为每个对等体选择一个ID。
var peer = new Peer(id, options)
在这里, 如果我们希望服务器为我们生成一个ID, 则可以完全省略id。就我们而言, 这就是我们要做的。 PeerServer将确保其给出的ID是唯一的。第二个参数, options, 通常是一个包含密钥的对象(API密钥, 如果你使用的是云托管的PeerServer, 或者如果你自己托管PeerServer, 则为主机, 端口, 路径等)。
var peer = new Peer({
host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs'
})
为了在两个PeerJS对等体之间建立连接, 其中一个对等体必须知道另一个对等体的ID。为了简单起见, 在我们通过WebRTC实现四人连线时, 我们将要求开始游戏的玩家与对手分享其对等ID。有了目标对等方ID后, 我们只需要简单地调用peer.connect(destId):
var conn = peer.connect(destId)
peer.connect(destId)返回的Peer对象和DataConnection对象都发出一些非常有用的事件, 值得监听。在本教程中, 我们对DataConnection对象的”数据”事件和两个对象的”错误”事件特别感兴趣。
为了将数据发送到连接的另一端, 只需调用conn.send(data):
conn.send('hello')
尽管对我们这里的需求有些过分, 但PeerJS在对等体以BinaryPack格式编码后在对等体之间传输数据。这使同级可以交流字符串, 数字, 数组, 对象甚至blob。
要接收传入的数据, 只需在conn上监听” data”事件:
conn.on(‘data’, function(data) {
// data === 'hello'
})
这几乎就是我们所需要的!
游戏逻辑
显示第一个开始游戏的玩家的对等ID(由PeerJS生成), 他们可以与对手共享。一旦对手使用第一个玩家的对等ID加入游戏, 则允许第一个玩家移动。
Connect Four是一种简单的规则和机制游戏, 只有一种移动方式:每个玩家都必须选择一列并将光盘放入其中。这意味着对等方需要通信的是当前播放器选择放入其光盘的列号。我们将以包含两个元素的数组的形式传输此信息:字符串” move”和数字-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(style='display: none;')
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(style='display: none;')
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。
第二位玩家可以单击, 然后单击”加入”按钮, 输入第一位玩家的对等ID, 然后开始游戏。
尝试一下
你可以在https://arteegee.herokuapp.com上试用此示例应用程序。
或者, 你可以从GitHub克隆存储库, 安装NPM依赖项, 然后在本地尝试:
git clone https://github.com/hjr265/arteegee.git
cd arteegee
npm install
PORT=5000 npm start
服务器运行后, 你可以使用对等ID将Web浏览器指向http:// localhost:5000, 从一个选项卡开始游戏, 然后从另一个选项卡(甚至是其他具有WebRTC功能的Web浏览器)加入游戏。
你可以打开网络浏览器的控制台以查看一些调试信息, 因为在此示例应用程序中, PeerJS客户端已配置为执行详细日志记录。
但这对我不起作用!
该游戏可能无法在你的计算机上运行的主要原因有两个。
你使用的网络浏览器可能不支持必需的WebRTC API。如果是这样, 你可能需要尝试使用其他浏览器-支持WebRTC和数据通道的浏览器。
如果你使用的是支持WebRTC的现代Web浏览器, 则可能存在WebRTC无法渗透的某些网络基础架构。理想情况下, 可以使用TURN服务器轻松解决此问题, 但是由于示例应用程序未使用该服务器, 因此当你和你的对手都位于NAT之后时, 该应用程序将无法工作。
总结
WebRTC是一项新技术, 其实现还远远不成熟。这些通常会给开发人员带来一些独特的挑战。但是, 随着像PeerJS这样的库的出现, 它们可以很好地抽象出粗糙的原始API, 该技术已经变得可以访问。
我希望这个有关构建基于PeerJS的游戏的简短教程将帮助你入门WebRTC并构建一些惊人的实时对等Web应用程序。