我正在编写一个 HTML5 游戏服务器。服务器包含一个比赛列表,当用户加入其中一场比赛时,他们可以看到比赛的进度,以及与其他用户聊天等。
当用户加入比赛时,服务器会在其 session 对象中查找“userid”字符串。 userid 字符串指的是一个用户对象。如果未找到,则会创建一个新的用户对象,并将“userid”字符串添加到 session 对象中。
这允许用户使用多个选项卡/窗口连接到多个游戏,同时仍然显示相同的用户名,并在每个窗口中显示图片。
现在的问题是处理同一用户多次连接到同一场比赛。如果用户有两个窗口连接到同一个游戏,我希望他们在两个窗口上看到完全相同的内容 - 有点像 Facebook 聊天。
目前,当用户连接到匹配项时,会创建一个新的“连接”对象,并在该对象上处理套接字事件等。
我希望能够做的是使用相同的事件处理函数来处理多个套接字的事件。唯一阻止我的是套接字事件没有“所有者”参数。由于没有引用接收消息的套接字,我无法将消息广播到除接收消息的套接字之外的所有套接字。
SocketIO Rooms 也不符合我的要求,因为 channel 上收到的消息没有事件。
我被迫考虑的是同时拥有一个连接对象和一个参与者对象,其中每个参与者都有多个连接。这让我感觉很臃肿。
另一种选择是尝试强制自己使用意大利面条式代码编写并利用闭包等。
确实需要有类似情况的人提供一些建议。
最佳答案
产品化解决方案:强制用户使用一个窗口。
如果用户已经连接并且服务器知道这一点,请让第二个窗口显示一个对话框,
You already have another window open with AwesomeGame. Please use that window or click the button below.
Use this window
如果用户单击该按钮,则通过 SocketIO 发送一条消息,声明该连接是代表用户的连接。然后,服务器将通知所有先前的连接它们已被取代。
工程解决方案:为每个客户端提供一个 token ,他们可以使用该 token 通过 SocketIO 向服务器进行身份验证。
生成并提供 HTML 后,在页面上包含用户 ID,并使用服务器已知的 key 对其进行签名。例如,我们的 token 如下所示:
<user id>|<salt>|<SHA1 hash of uid + salt + secret key>
当客户端连接时,忽略所有消息,直到客户端通过提供签名 token 进行身份验证。服务器可以分解 token 并验证 SocketIO 客户端确实代表该用户。
在服务器上,使用 pubsub 系统使用用户 ID 订阅打开的 SocketIO 连接。当消息绑定(bind)到特定用户时,将其发布到该用户ID。
关于javascript - Socket.io:如何处理打开两个窗口的经过身份验证的客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7948811/