XMPP网络聊天:如何解决多个选项卡/窗口?
我们有一个网站,并使用 strope.js 库和 ejabberd XMPP 服务器为其开发了一个聊天系统。我们使用通过 PHP 启动的会话附件(使用内部库)。我们所做的就是从 PHP 脚本中获取 RID 和 SID,然后使用 strope 的会话附件。所述 RID 和 SID 存储在 cookie 中,每次 strope.js 上的 RID 更新时,cookie 上的 RID 值都会更新。 (这样我们就可以在页面刷新/导航到网站上的其他位置时重复使用会话 ID)
我们现在计划让它在多个选项卡/窗口上工作。我观察了 Facebook 的实现,对于每个选项卡,都有一个针对特定域的长轮询请求。每个选项卡的该域都不同。例如,选项卡一为 0.86.channel.facebook.com。第二个选项卡是 1.86.channel.facebook.com。据我了解,这是为了解决浏览器对某个域的 2 个活动请求的限制。这个多域解决方案是如何实现的?
接下来是聊天会话本身。每个选项卡的聊天会话会有所不同,对吗? UI 如何与 Facebook 一样与每个选项卡同步?我的想法是,每个操作都会向用户自己的 JID 发送一条消息,其中包含与聊天相关的操作。例如,打开聊天窗口将发送如下消息节:
<message from="my_own_jid" to="my_own_jid" type="chat">
<body>{"jid-of-contact":"open-chat-box"}</body>
</message>
这将在聊天客户端上捕获,并且 UI 将进行相应调整(在本例中,为联系人打开聊天框)。
对此实施有何建议/意见?
谢谢!
We have a site and we developed a chat system for it using strophe.js library and ejabberd XMPP server. We use session attachment that was initiated with PHP (using an in-house library). What we do is get the RID and SID from the PHP script, then use strophe's session attachment. The said RID and SID is stored on a cookie and the RID value on the cookie is updated every update of the RID on strophe.js. (This is so we can reuse the Session ID on page refresh/navigation to other places on the site)
We now plan on having it work on multiple tabs/windows. I've observed Facebook's implementation, and for each tab there is a long polling request to a certain domain. This domain is different for each tab. For example, tab one would be 0.86.channel.facebook.com. Second tab would be 1.86.channel.facebook.com. As I understand this is to solve browser limitation of 2 active requests to a certain domain. How is this multiple domain solution implemented?
Next would be on the chat sessions itself. The chat sessions would be different per tab right? How would the UI be synched with each tab like Facebook? My idea is, per every action, a message would be sent to the user's own JID containing the action done related to chat. For example, opening a chat window would send a message stanza like this:
<message from="my_own_jid" to="my_own_jid" type="chat">
<body>{"jid-of-contact":"open-chat-box"}</body>
</message>
and this would be caught on the chat client and the UI would be adjusted accordingly (in this case, opening a chat box for a contact).
Any suggestions/comments on this implementation?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我和我的团队正在研究完全相同的问题 - 只是我们使用 Openfire 而不是 Ejabberd(主要是因为我们拥有 Java 技能但不熟悉 Erlang)。我们公司正在开发浏览器游戏。
我们的解决方案包括:
我们使用旁遮普语,因为 Openfire 的 BOSH 实现一开始似乎与其他组件配合得不太好。
基本上我们决定不为每个选项卡创建一个会话。这是因为我们的一些游戏的工作方式与通常网站的工作方式相同:单击链接将请求一个完整的新页面(而较新的游戏完全在 ajax 中工作,并且大多数 GUI 保持不变)。换句话说:我们基于网络的聊天必须在用户“在网站上移动”的环境中运行。一个选项卡的一个会话意味着每个页面请求都有一个新会话,这似乎是一项巨大的开销,因为玩家通常点击得很快。因此,我们希望创建一个会话并粘在一名玩家身上。
为了解决这个问题,我们和您一样修改了 strope.js 以在 cookie 中读取/保存 RID,以便所有选项卡都知道当前的 RID 并递增到正确的值。另一件事是,我们让 Strope 将 CID 添加到 XMPP 节的正文中。 CID 类似于客户端 ID。我很快就会解释其用途。
接下来的计划是修改旁遮普语中的两件事。首先,我们添加了一个类,它取代了在旁遮普语中存储等待请求的常用方式。等待的 BOSH 请求现在保存在字典中,并以 CID(strope.js 现在添加到每个请求的正文中)作为键。当来自同一选项卡的另一个请求到达旁遮普时,旁遮普就知道要向哪个等待请求发送空答案。如果有新的节要传送,旁遮普语会将这些节发送给字典中所有等待的请求。因此传入的消息会分发到所有选项卡。其次,我们添加了几行,以便从一个选项卡发送的消息立即“返回”到所有其他选项卡。因此该消息也可以出现在其他选项卡历史记录中。
当然,还必须面对其他问题,例如当玩家进入下一个屏幕时不会丢失 GUI 中的聊天历史记录。将其存储在 cookie 中会很糟糕,因为所有这些内容都会随每个请求一起发送并导致大量流量。为此,我们考虑实施类似于 XEP-0136 消息归档的东西。
简而言之,我们必须处理修补/扩展 strope.js 和旁遮普语的问题,并且我们正在对标准进行一些修改。但目前它运行良好,我很高兴看到这个设置在测试版中的表现。
Me and my team were working on the exact same problem - only that we use Openfire instead of Ejabberd (mostly cause we have Java skills but are not familiar with Erlang). Our company is building browsergames.
Our solution consists of:
We use punjab, because the BOSH implementation of Openfire did not seem to work very well with the other components at first.
Basically we decided not to create a session for each tab. This is due to the fact that some of our games work the way usual websites do: a click on a link will request a complete new page (whereas the newer games fully work in ajax and most of the GUI stays the same). So in other words: our web based chat will have to work in environments where the user 'moves over the website'. One session for one tab would mean a new session for each page request, which seems like a huge overhead, because players often click pretty quickly. So - we wanted one session to be created and stick to a player.
To solve that we - like you - modified strophe.js to read/save the RID in a cookie, so all tabs know the current RID and increment to a correct value. Another thing is, we made Strophe add a CID to the body of the XMPP stanzas. CID like Client ID. I'll explain the use soon..
Next the plan was to modify two things in punjab. First we added a class that replaced the usual way that waiting requests are stored in punjab. Waiting BOSH requests are now saved in a dictionary with the CID (that strophe.js now adds to the body of every request) as the key. When another request from the same tab arrives punjab then knows which waiting request to send an empty answer to. If there are new stanzas to be delivered punjab will send these out to all waiting requests in the dictionary. So an incoming message is distributed to all tabs. Second we added a few lines, so that a message that has been sent from one tab is delivered 'back' to all other tabs right away. So the message can appear in the other tabs history, too.
Of course there are other problems that have to be faced, like not loosing the chat history in the GUI when the player moves on to the next screen. Storing this in a cookie would be bad, since all that stuff is sent out with each requests and causes lots of traffic. For this we thinking of implementing something which is similar to XEP-0136 message archiving.
So to put it in a nutshell, we had to dealt with patching/extending strophe.js and punjab and we are modifying the standards a little. But it works fine for now and I am excited to see how this setup will do in the beta.
我的解决方案:
每个选项卡在不同的资源上都有自己的连接,所有连接的优先级都是1。
在openfire中添加服务器变量
route.all-resources: true
消息将广播到所有资源。
My solution:
Each tab has his own connection on different resource, all with priority 1.
In openfire add server variable
route.all-resources: true
Messages will be broadcast to all resources.