我是websockets的新手。我刚刚完成了我的第一个多用途套接字服务器,它在同一个套接字中提供3种类型的消息。此服务器的预期用途如下:
chat messages
real time market data
user specific alerts前两个函数工作得很好,我非常高兴,但是在识别和链接连接到特定帐户中的对等点时,我完全不知所措,这样我就可以向特定用户提供挂起的警报通知。
基本上,我将警报消息存储在数据库表中,如下所示:
Table: uc_notifications
account(varchar50) | message(varchar255) | id(primary,AI) | seen(default 0)我想把同龄人存储在这样的桌子上:
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数组转换成全局数组,但每次都是空的。我搜索了一下,然后尝试序列化数组。直到我将消息发送给唯一的对等方为止,这一切都很有效。
下面是发送消息的函数
function send_message_single_client($msg,$client)
{
@socket_write($client,$msg,strlen($msg));
return true;
}下面是我使用此函数将最后100条消息推送到新对等方的chatbox的示例。
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,不相关,但我想我会提到它,因为它有一些怪癖,迫使我稍微修改代码。
发布于 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。
https://stackoverflow.com/questions/23101377
复制相似问题