在两个私有频道之间发布PubNub消息

18

我正在使用Php和MySQL。

我刚注册了Pubnub推送API,成功地使用Pubnub提供的PHP Push API发送了第一条推送通知。我对这种实时技术还很陌生,所以我有一些问题让我自己感到困惑。我已经搜索了很多次并在stackoverflow上搜索了所有内容。我没有得到任何相关的建议或其他问题,所以我在这里写下我的问题,寻求您的意见和专业知识帮助。

Pubnub说每个客户端不应创建超过两个频道。因此,在我的应用程序中,我需要创建更多的频道来监听网站上发生的通知,但是我将按照Pubnub的建议为每个登录用户使用两个频道。

  1. Logged in users listens to Channel1-Public
  2. Logged in users listens to private UsersOwnDynamic-Channel to receive notifications related and only meant for him.

FYI: 该链接在PubNub中说长通道名称可以避免频道窃听

我的问题如下:
A.我是否总是需要在登录网站时创建新的私有动态频道名称?如果是这样,其他用户如何知道如何向我的私有频道发送通知?或者,我只需要在数据库表中存储一个静态频道名称,这样其他已认证的用户将查询该表并获取我的私有频道名称以向我发送通知。如果是这种情况,您不认为如果黑客掌握了某些用户的某些私有频道名称,他们将能够收听该频道吗?

B.我正在使用PHP和MySQL,因此仍然无法想出一种方法或想出解决方案,以便向另一个用户的私有频道发送消息。
让我们以简单的好友请求系统为例。
-UserA向UserB发送好友请求。
-UserB正在监听自己的动态私人频道名称DynamicPrivateChannelB
(UserA如何找到UserB的私人频道名称?我认为这唯一的方法是将UserB的私人频道存储在数据库表中,以供每个登录的用户进行查询。我是否想得对?)

<?php 

    //first way. How can i possibly achieve this.
    $sqlquery = "sent friend request from userA to userB"; 
    require('Pubnub.php'); 
    $pubnub = new Pubnub( 'pubkey', 'subkey' );
    $pubnub->publish( array(
        'channel' => 'how do i find the private channel name for userB to sent this notification?', 
                    'message' => array('friend_request' => 'A friend request') ) 
                    );

  //2nd way ? Is this the right way ?
    $sqlquery = "sent friend request from userA to userB"; 
    $privatechannelofuserB = "get the channel name of userB from the db table";
    require('Pubnub.php'); 
    $pubnub = new Pubnub( 'pubkey', 'subkey' );
    $pubnub->publish( array(
        'channel' => '$privatechannelofuserB', 
                    'message' => array('friend_request' => 'A friend request') ) 
                    );
?>

C. 如果我们总是生成动态的私人频道名称,存储在数据库表中,并在每次生成新的动态频道名称时更新。我认为这会导致问题,因为一些消息无法传递,当新的动态私人频道名称替换旧的名称时。

D. 所以,我需要向单个频道发送许多通知,例如新的朋友请求、新的私人信息回复、新的礼物请求等等。我如何将所有这些数据发送到一个频道,并如何查找和解析传入的新通知数据。我知道JSON是要发送的格式,但我不确定发送的格式。

根据此链接,单个Pubnub频道最多只能包含100条消息。这是否意味着如果一次性有200条消息发送到单个频道,前100条就会被发送并且剩余的在队列中?如果一次性有10,000条消息发送到单个频道,剩下的所有消息都留在队列中吗?如果是这样,它们如何即时地传递给订阅者呢?

让我给出另一个我正在尝试实现的简单场景。

  • UserA已通过身份验证并登录到网站。
  • UserA生成了自己的动态频道名称,UserAx732dsw3efsdfsdfsdf
  • UserA开始监听他新创建的频道UserAx732dsw3efsdfsdfsdf
    (现在,userA应开始收到来自其他人的消息)


- UserBuserA发送私人消息。
(现在,只有用户A应该在他的私人频道上收到关于新私人消息的通知,但是,UserBSystem如何找到频道名称UserAx732dsw3efsdfsdfsdf,因为这是userA动态生成的私有频道,系统或userB都没有访问它。如果任何其他实体或系统再次通知userB,同样的事情也正在发生,必须有一种方法找到userB的动态频道名。另一个问题是,如果用户每次登录网站时都会动态生成频道名称,那么所有发送到动态频道的消息会发生什么?Pubnub是否保存了所有创建的频道名称到其服务器上?系统或用户是否有办法找出频道名称是否仍在使用,并且至少有一个用户正在监听该频道?

我想了解这个问题,因为我有以下概念:

  • UserA1AM登录网站时创建了dynamicChannelA
  • UserA开始接收大量的通知推送到他的动态频道dynamicChannelA
  • 现在,在1:30 AMUserA从网站注销,那么仍然向他的dynamicChannelA发送通知的许多其他用户会发生什么,因为下一次当UserA登录网站时,UserA将听取不同的动态频道名称。 UserA将不会听他以前的频道dynamicChannelA


我正在考虑使用从数据库表中检索特定用户频道名称的方法。是否有任何方法或方式可以防止未经授权的订阅?因为无论频道名称多长,只要有订阅键和频道名称,任何人都可以订阅频道


嗨,RT Roger。谢谢你的问题!这是一个非常详细的清单。我们将在本周提供反馈。 - Stephen Blum
非常感谢您让我知道,我会等待反馈。 - RT Roger
如果有用的话,请查看此答案:https://dev59.com/u5_ha4cB1Zd3GeqP486G#42860273 - Maytham Fahmi
@RTRoger 我也有同样的疑问。 - Arj 1411
1个回答

30
"没有一种单一的方法可以解决你遇到的问题。我们的客户使用了各种设计模式来处理它们。我自己在构建PubNub应用程序时也遇到了这种情况,我会尽力帮助你。
Pubnub表示每个客户端创建不超过两个频道并不是一个好习惯。因此,在我的应用程序中,我有一个需要创建多个频道以便监听网站上发生的通知,但是我将按照Pubnub建议为每个已登录用户创建两个频道。
已登录用户可以监听Channel1-Public和private UsersOwnDynamic-Channel以接收仅与他相关且仅针对他的通知。这是一个很好的方式,也是我们许多大规模客户采用的方式——一个全局频道和一个私人、仅针对用户的频道。
A.
“每次我登录网站时,我是否总是需要创建一个新的私人动态频道名称?”
不一定,但这是一个好方法。您可以在客户端使用JavaScript中的PUBNUB.uuid()来实现此目的。或者,使用PHP在服务器端生成它并呈现给客户端。也许您可以将其设置为cookie,以便客户端始终可以访问它。
如果是这样,其他用户如何知道如何向我的私有频道发送通知?
他们可以从PHP服务器获取ID;通过全局通道或用户自己的私有通道,他们正在监听。
还是说,我只需要在数据库表中存储一个静态频道名称,以便其他经过身份验证的用户将查询该表并获取我的私有频道名称以向我发送通知?
您也可以这样做。您可能希望用户可以发送到的全局频道与他们正在监听的全局频道不同。只有服务器拥有那个订阅密钥。因此,经过身份验证的用户向服务器发送消息,告诉它“我需要适当的用户密钥”,然后服务器进行查询并在该用户的私有频道上发送消息回来。
如果是这种情况,你不觉得黑客获取某些用户的私有频道名称时,他们将能够收听该频道吗?
如果在全局发送通道上保留订阅密钥,则只有服务器才能看到该通道上的聊天内容。
我正在使用PHP和mysql,所以我仍然无法想出一种方法或提出一种解决方案,以将消息发送到另一个用户的私有频道。 以简单的好友请求系统为例:- UserA向UserB发送好友请求。- UserB正在听自己的动态私人频道名称DynamicPrivateChannelB(UserA如何找到UserB的私人频道名称?我认为唯一的方法是将UserB的私人频道存储在数据库表中供每个登录的用户查询。我想对了吗?)
这与您之前的问题非常相似。没有一个固定的方法,但是我上面概述的设计模式应该有效。回顾一下这种设计模式:
服务端
  • 监听 Global-user-send-channel 以获取用户消息。服务器是唯一拥有此订阅密钥的实体。
  • 可以查询数据库以获取用户 ID,然后随意发送到各个 ID。
  • 也可以在 Global-user-receive-channel 上发送消息,所有客户端都在监听此通道。服务器是唯一拥有此发布密钥的实体。

客户端

  • 在 Global-user-receive-channel 上监听。这是它接收来自服务器的广播消息的方式。不能在此通道上发送消息(只有订阅密钥)。
  • 在 Global-user-send-channel 上向服务器发送消息。不能在此通道上接收消息(只有发布密钥)。
  • 在私人用户频道上监听。这是用户收到私人消息的方式。它还可以将其用于客户端之间的通信。
  • 通过将所有私人消息附加上存储在服务器上的私有、每个用户密钥,并在初始页面加载时提供,以防止滥用。这样,客户端就知道声称来自服务器的消息是否合法。

C.

如果我们总是生成动态的私有频道名称,存储在数据库表中,并在生成新的动态频道名称时进行更新。我认为这会导致问题,因为一些消息由于新的动态私有频道名称替换旧的名称而无法传递。
如果您在生成新频道名称时小心谨慎,这不应该是一个问题。请记住,客户端始终可以在全局用户发送通道上说“嘿,我在这里!这是我的ID,请保持更新”。我通常设计我的应用程序,让客户端每隔30秒左右自动发出这个请求。
所以,我有很多通知要发送到单个频道,比如新朋友请求、新私人消息回复、新礼物请求等等。我如何将所有这些数据发送到一个频道,并且如何找到和解析传入的新通知数据。我知道JSON是发送的格式,但我不确定发送的格式。
JSON很适合发送和接收。我做的方法是有一个叫做“name”的属性,它定义了消息的类型。例如:
{
    "id"   : "blah_blah_unique_id",    // sender_client_id 
    "name" : "friend_request",         // type of message
    "data" : {                         // the data itself
               "requested_friend_id" : "blah_blah_some_other_unique_id" 
             }
}

你实际上可以使用任何格式,但当它通过 PubNub 传输时,我们会将其包装在 JSON 中(通常意味着只需用引号括起来)。
希望这能帮到你!
新问题
根据 此链接,单个 Pubnub 频道最多只能包含100条消息。这是否意味着如果200条消息同时发送到单个频道,则前100条消息会被传递,剩余的则排队等待?如果一次有10,000条消息发送到单个频道,情况如何?所有剩余消息都会排队等待吗?如果是这样,如何实时将其传递给订阅者?
100条消息的限制是关于 PubNub.history 的。如果有人订阅并且有200条消息进来,他们将收到所有200条消息。
现在,只有用户A应该在他的私人频道上收到有关新私人消息的通知,但是,用户B或系统如何找出频道名称UserAx732dsw3efsdfsdfsdf,因为这是由用户A动态生成的私人频道,系统或用户B都无法访问。 对于用户B也是同样的情况,如果任何其他实体或系统应该通知用户B,应该有一种方法来找到用户B的动态频道名称。
对于这个问题没有万能的解决方案,但我会让服务器在页面加载时生成唯一的ID,并在初始HTTP请求上将其呈现给客户端。
另一个问题是,如果用户每次登录网站时都动态生成频道名称,那么会发生什么情况?所有发送到动态频道的消息会发生什么?pubnub是否保存其服务器上创建的所有频道名称?
您不必每次动态生成。 您可以......但是您还可以设置带有该唯一ID的cookie,或从数据库中提取并在页面加载时呈现给客户端(这是我要做的)。 我们不保存频道名称。

是否有办法让系统或用户找出频道名称是否仍在使用,并且至少有一个用户正在收听该频道?

默认情况下是不行的,但您可以轻松实现此操作。只需让您的服务器发送ping并设置您的客户端始终响应ping,如果他们正在收听,则可实现。

现在,UserA在凌晨1:30从网站注销,那么仍在向他的dynamicChannelA推送通知的其他许多用户会发生什么情况?因为下次UserA登录网站时,UserA将收听不同的动态频道名称。UserA将不再收听以前的频道dynamicChannelA。

避免这种情况的方法是让服务器定期(每30秒)发送ping,以便跟踪用户是否仍在使用。顺便说一下,在未来几个月中,我们将推出一个“在线状态API”,可以自动完成此操作。

我打算使用从数据库表中检索特定用户频道名称的方法。是否有任何方法或方式可以防止未经授权订阅频道?因为只要拥有订阅密钥和频道名称,任何人都可以订阅频道名称,无论频道名称有多长。我只是好奇,因为所有订阅都在客户端发生,订阅密钥和频道名称都是可见的。
主要的方法是有策略地保留发布/订阅密钥。你说得对,任何具备适当细节的人都可以收听 - 这是仅客户端系统的一个大问题。目前,您必须想出有创意的方法来解决它。

你好@Phil Deschaine,非常感谢您对上述设计模式的宝贵见解。那么,您是说我的服务器端代码可以订阅频道并响应传入的消息,处理并向其发送方发布消息?我是否需要运行一个特殊的PHP脚本在后台订阅全局用户发送通道,这样做对吗?您认为它会消耗大量服务器内存和资源吗?此外,请您检查一下我上面的问题,我在阅读您的答案后添加了更多问题。非常感谢您的回复。 - RT Roger
1
@RTRoger 如果这个答案有帮助,请接受它。 - Matt Harrison

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接