Php 拉威尔+;棘轮:将通知推送到特定客户端
我是WebSocket新手,我想在我的Laravel应用程序中实现这样的服务。 我已经读了好几篇关于这个主题的文章/页面,但没有一篇解释我需要做什么。所有这些都展示了如何创建一个“Echo”websocket服务器,其中服务器只响应从客户端接收到的消息,这不是我的情况 作为起点,我使用了以下提供的代码: 其中websocket服务器是从命令行或其他控制台运行的。服务器有自己的类来定义它,并导入WebSocketController类(MessageComponentInterface),该类包含经典的WebSocket服务器事件(onOpen、onMessage、onClose、onError) 所有这些都可以正常工作,但是,我如何“告诉”WebSocket服务器从另一个类(也属于另一个命名空间)向特定连接(客户机)发送消息呢?。这是通知或事件的情况,其中新的web内容必须发送到特定的客户端。没有来自客户端的订阅或发布 正如@Alias在他的帖子中所问的,我显然无法创建Websocket服务器或其事件管理类的新实例,那么向客户端发送内容或消息的最佳方法是什么 正如大家所看到的,通信只有一种方式:从WebSocket服务器到客户端,而不是相反。 我已经为此准备了一个通知类和一个侦听器类,但我仍然不知道如何通过handle()方法处理与客户端的通信:Php 拉威尔+;棘轮:将通知推送到特定客户端,php,laravel,notifications,pusher,ratchet,Php,Laravel,Notifications,Pusher,Ratchet,我是WebSocket新手,我想在我的Laravel应用程序中实现这样的服务。 我已经读了好几篇关于这个主题的文章/页面,但没有一篇解释我需要做什么。所有这些都展示了如何创建一个“Echo”websocket服务器,其中服务器只响应从客户端接收到的消息,这不是我的情况 作为起点,我使用了以下提供的代码: 其中websocket服务器是从命令行或其他控制台运行的。服务器有自己的类来定义它,并导入WebSocketController类(MessageComponentInterface),该类包
好的,在学习和研究了很多之后,我可以把一个类似问题的答案发布在: 根据我在这篇文章的第二条评论中所写的内容,这就是我找到的解决方案 我使用composer为websocket服务器安装了cboden/Ratchet包。 当后端触发事件时,我需要向用户/用户组发送通知,或更新UI 我所做的是: 1)使用composer安装了AmHP/websocket客户端软件包 2)创建了一个单独的类,以便实例化可以连接到websocket服务器的对象,发送所需消息并断开连接:
namespace App;
use Amp\Websocket\Client;
class wsClient {
public function __construct() {
//
}
// Creates a temporary connection to the WebSocket Server
// The parameter $to is the user name the server should reply to.
public function connect($msg) {
global $x;
$x = $msg;
\Amp\Loop::run(
function() {
global $x;
$connection = yield Client\connect('ws://ssa:8090');
yield $connection->send(json_encode($x));
yield $connection->close();
\Amp\Loop::stop();
}
);
}
}
3)webSocket服务器处理程序类中的onMessage()
事件如下所示:
/**
* @method onMessage
* @param ConnectionInterface $conn
* @param string $msg
*/
public function onMessage(ConnectionInterface $from, $msg) {
$data = json_decode($msg);
// The following line is for debugging purposes only
echo " Incoming message: " . $msg . PHP_EOL;
if (isset($data->username)) {
// Register the name of the just connected user.
if ($data->username != '') {
$this->names[$from->resourceId] = $data->username;
}
}
else {
if (isset($data->to)) {
// The "to" field contains the name of the users the message should be sent to.
if (str_contains($data->to, ',')) {
// It is a comma separated list of names.
$arrayUsers = explode(",", $data->to);
foreach($arrayUsers as $name) {
$key = array_search($name, $this->names);
if ($key !== false) {
$this->clients[$key]->send($data->message);
}
}
}
else {
// Find a single user name in the $names array to get the key.
$key = array_search($data->to, $this->names);
if ($key !== false) {
$this->clients[$key]->send($data->message);
}
else {
echo " User: " . $data->to . " not found";
}
}
}
}
echo " Connected users:\n";
foreach($this->names as $key => $data) {
echo " " . $key . '->' . $data . PHP_EOL;
}
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients[$conn->resourceId] = $conn;
echo " \n";
echo " New connection ({$conn->resourceId}) " . date('Y/m/d h:i:sa') . "\n";
}
如您所见,希望websocket服务器将消息发送到的用户在$msg参数中与消息本身($data->message)一起指定为字符串($data->to)。这两个东西都是JSON编码的,因此参数$msg可以被视为一个对象
4)在客户端(布局刀片文件中的javascript),当客户端连接时,我将用户名发送到websocket服务器:
var currentUser = "{{ Auth::user()->name }}";
socket = new WebSocket("ws://ssa:8090");
socket.onopen = function(e) {
console.log(currentUser + " has connected to websocket server");
socket.send(JSON.stringify({ username: currentUser }));
};
socket.onmessage = function(event) {
console.log('Data received from server: ' + event.data);
};
因此,用户名及其连接号保存在websocket服务器中
5)处理程序类中的onOpen()
方法如下所示:
/**
* @method onMessage
* @param ConnectionInterface $conn
* @param string $msg
*/
public function onMessage(ConnectionInterface $from, $msg) {
$data = json_decode($msg);
// The following line is for debugging purposes only
echo " Incoming message: " . $msg . PHP_EOL;
if (isset($data->username)) {
// Register the name of the just connected user.
if ($data->username != '') {
$this->names[$from->resourceId] = $data->username;
}
}
else {
if (isset($data->to)) {
// The "to" field contains the name of the users the message should be sent to.
if (str_contains($data->to, ',')) {
// It is a comma separated list of names.
$arrayUsers = explode(",", $data->to);
foreach($arrayUsers as $name) {
$key = array_search($name, $this->names);
if ($key !== false) {
$this->clients[$key]->send($data->message);
}
}
}
else {
// Find a single user name in the $names array to get the key.
$key = array_search($data->to, $this->names);
if ($key !== false) {
$this->clients[$key]->send($data->message);
}
else {
echo " User: " . $data->to . " not found";
}
}
}
}
echo " Connected users:\n";
foreach($this->names as $key => $data) {
echo " " . $key . '->' . $data . PHP_EOL;
}
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients[$conn->resourceId] = $conn;
echo " \n";
echo " New connection ({$conn->resourceId}) " . date('Y/m/d h:i:sa') . "\n";
}
每次客户端连接到websocket服务器时,其连接号或resourceId都存储在一个数组中。因此,用户名存储在一个数组($names)中,密钥存储在另一个数组($clients)中
6)最后,我可以在项目中的任何位置创建一个PHP websocket客户端(wsClient)实例,向任何用户发送任何数据:
在本例中,我使用通知事件侦听器的handle()方法
好的,这是为那些想知道如何从PHP websocket服务器(也称为echo服务器)向一个特定客户端或一组客户端发送消息的人准备的。好的,我一直在玩RatchetPHP/Pawl,它可以作为PHP客户端工作,但它也会阻止我的javascript websocket客户端。一旦Pawl断开连接,javascript websocket客户端就会连接。这看起来像是Pawl创建的循环,阻止了js客户端。我需要用PHP向JS websocket客户端发送通知,而不阻止它们。通过安装Amhp/websocket客户端,我可以建立一个PHP客户端连接,向websocket服务器发送消息,并告诉它将回复发送到另一个连接。但是,如果用户浏览应用程序菜单/链接,则随后的HTML请求会断开javascript websocket客户端的连接。读一读关于它的文章,我需要将JSWebSocket保存在web worker中,以保持连接的活力。如果没有,将在下一页创建一个新连接,这将使维护变得更加困难,并生成更多的网络流量来更新连接表/列表。