在Mac App上测试Phoenix频道

在Coletiv的当前项目之一中,我们需要不断保持数据在多个移动设备之间的同步。 我们想到的使状态保持最新的第一个解决方案是每分钟与推送通知相关的服务器轮询服务器。

显然,就性能和可靠性而言,这并不是最佳的解决方案。 由于我们的后端是使用Phoenix制造的,因此最初的天真解决方案自然就演变为使用Phoenix Channels。

在本文中,我们将介绍我们使用游戏“史莱姆足球”实现概念验证以测试Phoenix Channel的经验。 对于两个玩家来说,这是一个简单的游戏,每个人控制一个粘液,目标是进球。

概念证明已在Swift中作为Mac应用程序实现,但可以轻松地以您选择的任何其他语言或平台实现。

这个想法是让游戏的两个实例在不同的计算机上运行,​​每个实例都将通过Phoenix频道连接到Phoenix服务器。 服务器负责管理游戏得分并处理两个玩家之间的通信。


有几个Swift开源项目可以帮助进行渠道沟通:

  • PhoenixWebSocket
  • 鸟鸣
  • Swift Phoenix客户

我们之所以选择使用Birdsong,只是因为我们认为目前最适合我们需求的项目。 它具有简洁的代码样式,对服务器执行定期ping操作,并允许进行一些自定义操作,例如处理断开操作。

如果要继续学习,可以在此处找到服务器源代码,在此处找到客户端源代码。

下图描述了游戏过程中Mac客户端与服务器之间的一般通信流程。

服务器

要在Phoenix中定义一个新通道,我们只需将此行添加到UserSocket.ex中:

 频道(“游戏:*”,SuperSlimeGameWeb.GameChannel) 

我们的连接功能非常简单,因为我们选择忽略身份验证步骤,因为这将意味着需要进一步的开发,而这并不是我们进行此测试的目标,但是如果您需要身份验证,则可以在此进行检查。

客户

在connect方法中,我们定义了onConnectonDisconnect处理程序。 连接/断开套接字后,将调用这些闭包。 在我们的测试中,我们将在连接套接字后立即加入通道。 当插座断开连接时,将在短暂的延迟后执行重新连接。

服务器

该应用程序的主要部分是加入功能,玩家可以在其中加入游戏。 信道术语和有效载荷结构定义如下:

通道命名

 “游戏:” 代码 

有效载荷结构

  %{“电子邮件” =>电子邮件} 

游戏代码game:[a_code]用于检查游戏是否已经存在于为管理游戏而创建的GameState代理进程中。 如果游戏已经存在,我们将添加通过有效负载结构传递的新玩家,否则将创建新游戏并添加新玩家。

GameState代理用于保存游戏和比赛玩家,它作为受监督的子进程与服务器一起启动。

要启动代理,将工作器添加到Application.ex中,如下所示:

 工作者(SuperSlimeGame.GameState,[]) 
游戏状态代理实施

客户

在join方法中,我们定义了通道事件监听器。 如果从通道返回了特定的操作(即播放器已移动),则将执行这些侦听器。 验证套接字的状态以确保维持连接的持久性很重要。

服务器

收到playerAction命令后,服务器会将其广播给所有加入该频道的播放器。

客户

每次更新场景时,都会向通道发送一条消息,其中包含本地玩家的坐标和动作。


身份验证方法-连接与连接

在此示例中,我们没有在通道连接中添加任何安全性,但这在现实环境中是必须具有的。

在Coletiv开发的其他项目中,我们需要验证用户身份以允许其访问其资源。 这通常是通过使用Guardian + ueberauth + JWT + Comeonin来完成的。 这里我们关心的是在connectjoin函数中发送JWT令牌。

我们决定在connect函数中使用它,因为没有有效的令牌,没有人可以访问端点。 否则,如果在join函数中传递了令牌,则每个人都将执行成功的连接,从而使端点公开。

改善游戏交流/同步

在此游戏中,两名玩家都有责任绘制玩家位置并模拟游戏物理。 显然,这不是完成运动同步的最佳方法,也许主从策略可能是更好的解决方案。

确保使用HTTPS / WSS

服务器必须使用WSS协议接受传入的安全连接。 默认情况下,大多数服务器不接受此设置。

  #配置端点 
config:myapp,MyApp.Web.Endpoint,
网址:[主机:“本地主机”],
check_origin:[“ //dev.example.com”,“ //www.example.com”],
secret_key_base:“ SECRET_KEY”,
render_errors:[视图:MyApp.ErrorView,接受:〜w(json)],
pubsub:[名称:MyApp.PubSub,适配器:Phoenix.PubSub.PG2]

连接持久性

在客户端,保持套接字连接的活动性非常重要,这会导致更多的代码复杂性。 我们尝试通过在连接断开时实现reconnect()函数来实现此目的,但是如果我们需要重新加入通道和/或使用身份验证,这还不够。

在Phoenix Channels的体验中,我们注意到消息交换过程可靠且快速。 这款未经游戏优化的简单游戏具有令人满意的性能。

我们认为Phoenix频道可达到维持多个客户端之间状态同步的目的。

我们正在当前的一个项目中实施类似的解决方案,我们希望尽快写出我们在Phoenix Channels的真实经验。

您可以在此处找到服务器源代码,并在此处找到客户端源代码。

Interesting Posts