首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Websockets和标识唯一的peers[PHP]

Websockets和标识唯一的peers[PHP]
EN

Stack Overflow用户
提问于 2014-04-16 06:12:38
回答 1查看 2.9K关注 0票数 4

我是websockets的新手。我刚刚完成了我的第一个多用途套接字服务器,它在同一个套接字中提供3种类型的消息。此服务器的预期用途如下:

代码语言:javascript
复制
chat messages

real time market data

user specific alerts

前两个函数工作得很好,我非常高兴,但是在识别和链接连接到特定帐户中的对等点时,我完全不知所措,这样我就可以向特定用户提供挂起的警报通知。

基本上,我将警报消息存储在数据库表中,如下所示:

代码语言:javascript
复制
Table: uc_notifications

account(varchar50) | message(varchar255) | id(primary,AI) | seen(default 0)

我想把同龄人存储在这样的桌子上:

代码语言:javascript
复制
uc_notification_peers
account(varchar50) | peer_id(unique,varchar100) | id(primary,AI)

基本上,我遇到的问题是将对等方的信息存储在db中,并检索它,以便在读取通知表时将消息发送给select对等方。剧本里的其他东西都起作用了。

我尝试的第一件事是使用onopen将帐户名传递给websocket。这会使websocket崩溃。

我尝试的下一件事是通过与ip地址相关的全局访问用户会话。也没有工作,并导致所有帐户都在同一个ip上接收消息(我在本地主机上测试所有3种浏览器)。

我最后一次尝试的是第一种方法。我在on打开事件上设置了2秒的超时时间,然后发送帐户消息。我终于能在数据库中存储一个对等点了!但是,令我懊恼的是,当我检查数据库时,它说(“id#6资源”)。我试着将$clients数组转换成全局数组,但每次都是空的。我搜索了一下,然后尝试序列化数组。直到我将消息发送给唯一的对等方为止,这一切都很有效。

下面是发送消息的函数

代码语言:javascript
复制
function send_message_single_client($msg,$client) 
{
    @socket_write($client,$msg,strlen($msg));
    return true;
}

下面是我使用此函数将最后100条消息推送到新对等方的chatbox的示例。

代码语言:javascript
复制
if (in_array($socket, $changed)) {
        $socket_new = socket_accept($socket);
        $clients[] = $socket_new;
        $header = socket_read($socket_new, 1024);
        perform_handshaking($header, $socket_new, $host, $port);
        socket_getpeername($socket_new, $ip);
        $found_socket = array_search($socket, $changed);
        //need to push last 100 messages to new peer.
        $query = $mysqli->query("SELECT * FROM (SELECT * FROM uc_chat_msg WHERE `hidden`='0' ORDER BY `id` DESC LIMIT 100) as last100 ORDER BY id");
        while($row = $query->fetch_assoc()) {
            $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>security($row["username"]), 'message'=>security($row["message"]), 'color'=>security($row["color"]))));
            send_message_single_client($response_text, $socket_new);//send old messages to the new client
        }
        $query->close();
        unset($changed[$found_socket]);
    }

那是几周前的事了,我把这个项目放在次要位置,这样我就可以继续关注其他事情了。此后,我转到了一个开发版本,以适应不断增长的应用程序的大小/复杂性。而不是php,我使用的是facebooks,不相关,但我想我会提到它,因为它有一些怪癖,迫使我稍微修改代码。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-22 13:24:40

我对PHP一无所知,但我认为这更多地是一个方法问题,而不是编码问题。因此,我希望这些想法,从我的经验推送架构带来一些启示。

识别用户

cookie标识:

WebSockets使用HTTP握手,该握手将为该源发送cookie。您可以将一个临时ID (例如: GUID)附加到一个特别会话cookie,每次用户在同一个会话中重新连接时都会重新发送。只要您遵守相同的原产地策略,或者在HTTP握手响应本身中,您就可以从网站部署cookie。

象征性地识别:

当WebSocket连接时,您可以从服务器发送一条包含临时ID的令牌的初始消息。如果连接中断,该令牌可以在重新连接时重新发送,但如果用户重新加载页面,除非它保存在本地存储或任何其他类型的浏览器存储中,否则将被遗忘。

关于临时ID的说明

如何将临时ID映射到特定的用户或帐户,这是您不想泄露到web的实现细节。因此,不要使用这些信息来标识WS连接。

您应该保留一个“会话”注册表,该注册表将临时in映射到帐户,可能是从内存字典中的帐户映射到DB上的表。取决于你你的要求和你的服务。此元素必须保持对WebSocket连接的引用,以便在需要时可以通过临时ID检索它。

不要泄露内部详细信息,特别是帐户ids (因为它们不会更改)。

接收讯息

当从WebSocket接收消息时,您必须创建一个消息对象,该对象使用您保存的“会话”信息以及实际的消息内容来包含发件人帐户。然后,将此消息对象传递给您的业务逻辑,该逻辑将决定要做什么。

在发送消息之前

为了发送消息,必须定义前几个元素:

出席情况:

哪些账户在线?将“会话”存储与帐户表合并。当连接下降时,应该删除drops会话。

属于:

哪些帐户属于特定的组或信号?你必须根据你的要求来设计它。有些组可以在“帐户”实体中预定义和指示,另一些组可能是动态的,就像他属于聊天室一样。在任何情况下,您都需要另一个将“组”映射到“帐户”的元素。

发送消息

当您的业务逻辑决定它想要发送一个消息,或者作为对传入消息的响应,作为一个定时的操作,自己的主动性或其他什么。它必须决定必须向哪个用户帐户、用户帐户或用户组发送。

然后,使用您保存的会话信息,收集必须接收该消息的临时ID列表,然后收集必须将该消息转发到其中的WebSockets列表,最后将消息发送给该列表的每个WS。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23101377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档