3

我正在使用 rachetphp 为 api 服务器创建客户端。但是我有一个问题,当我的连接关闭时,无论什么原因,我都无法自动重新连接。

这里是我使用的库:https ://github.com/ratchetphp/Pawl

<?php

require __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$connector = new Ratchet\Client\Connector($loop);

$connector('ws://127.0.0.1:9000', ['protocol1', 'subprotocol2'], ['Origin' => 'http://localhost'])
->then(function(Ratchet\Client\WebSocket $conn) {
    $conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) {
        echo "Received: {$msg}\n";
        $conn->close();
    });

    $conn->on('close', function($code = null, $reason = null) {
        echo "Connection closed ({$code} - {$reason})\n";
    });

    $conn->send('Hello World!');
}, function(\Exception $e) use ($loop) {
    echo "Could not connect: {$e->getMessage()}\n";
    $loop->stop();
});

$loop->run();

我想在连接关闭后每隔几秒重新连接一次。有任何想法吗?

4

2 回答 2

5

这个想法很简单,但需要一些重构。我们必须将重新连接代码放在连接关闭时执行的处理程序中。为了做到这一点,我们将$app函数传递给 self.

require __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();
$connector = new Ratchet\Client\Connector($loop);

$app = function (Ratchet\Client\WebSocket $conn) use ($connector, $loop, &$app) {
    $conn->on('message', function (\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) {
        echo "Received: {$msg}\n";
        $conn->close();
    });

    $conn->on('close', function ($code = null, $reason = null) use ($connector, $loop, $app) {
        echo "Connection closed ({$code} - {$reason})\n";

        //in 3 seconds the app will reconnect
        $loop->addTimer(3, function () use ($connector, $loop, $app) {
            connectToServer($connector, $loop, $app);
        });
    });

    $conn->send('Hello World!');
};

function connectToServer($connector, $loop, $app)
{
    $connector('ws://127.0.0.1:9000', ['protocol1', 'subprotocol2'], ['Origin' => 'http://localhost'])
        ->then($app, function (\Exception $e) use ($loop) {
            echo "Could not connect: {$e->getMessage()}\n";
            $loop->stop();
        });
}

connectToServer($connector, $loop, $app);

$loop->run();

这个想法是,当连接接收到close事件时,我们使用以下connectToServer函数进行重新连接:

$conn->on('close', function ($code = null, $reason = null) use ($connector, $loop, $app) {
    echo "Connection closed ({$code} - {$reason})\n";

    //in 3 seconds the app will reconnect
    $loop->addTimer(3, function () use ($connector, $loop, $app) {
        connectToServer($connector, $loop, $app);
    });
});
于 2017-04-03T07:56:48.697 回答
0

如果您安装了 pnctl ( http://php.net/manual/en/book.pcntl.php ),您只需将“关闭”处理程序更改为:

$conn->on('close', function($code = null, $reason = null) {
    echo "Connection closed ({$code} - {$reason})\n";

    // restart myself
    global $argv;
    pcntl_exec($_SERVER['_'], $argv);
    exit();

}); 

对我来说,这更简单,因为我还没有提取 $loop 和 $connector,我只是在使用

\Ratchet\Client\connect($ws_url, [], $headers)
    ->then(function ($conn) {
        echo "connected\n";
        ...

为了在多个地方处理它,我创建了一个小助手函数,我在这些事件上调用它(根据情况,我添加了一个延迟)。

function restartMyself() {
  global $argv;
  pcntl_exec($_SERVER['_'], $argv);
  exit();
}
于 2018-08-14T10:15:35.233 回答