我目前正在开发一个PHP应用程序,它将使用一些websocket连接与另一个服务进行通信。
要与这个websocket服务交谈,我们正在使用Ratchet - 这是一个基于PHP反应的PHP库。
这段代码需要发送并响应几个请求,之后,应该将信息返回给“主线程”。
示例流程:
HTTP请求 - >控制器 - >启动一个打开websocket客户端的服务 - > websocket客户端正在与服务器通信 - >一旦完成它应该将结果返回到控制器代码 - >控制器输出到用户
我遇到的问题是我不熟悉Reactive PHP并且不确定如何处理这个问题。
我试过了;
$service = new WebsocketService();
$startTimer = time();
$service->getList(44);
while($service->getResponse() == null) {
usleep(500);
if (time() > $startTimer + 10) {
continue; //Timeout on 10 seconds
}
}
var_dump($service->getResponse());
一旦完成,服务代码将其“响应”变量设置为除null之外的其他值。这显然失败了,因为sleep方法阻塞了线程。也没有,似乎while循环阻塞I / O并且反应代码失败。
解决方案是打开一个新线程并在那里运行websocket代码,但我对此不满意。
我觉得我需要围绕websocket流程实现某种“观察者”,但我不知道该怎么做。
我们的Websocket服务客户端代码如下所示;
private $response = null;
/**
* @return null|object
*/
public function getResponse() {
return $this->response;
}
public function getList($accountId) {
$this->response = null;
\Ratchet\Client\connect('ws://192.168.56.1:8080')->then(function(\Ratchet\Client\WebSocket $conn) use ($accountId) {
$login = new \stdClass();
$login->action = 'login';
$conn->on('message', function($msg) use ($conn, $login, $accountId) {
try {
$response = json_decode($msg);
if ($response->result_id == 100) {
//Succesfully logged in to websocket server
//Do our request now.
$message = new \stdClass();
$message->target = 'test';
$conn->send(json_encode($message));
}
if (isset($response->reply) && $response->reply == 'list') {
$this->response = $response; //This is the content I need returned in the controller
$conn->close(); //Dont need it anymore
}
} catch (\Exception $e) {
echo 'response exception!';
//Do nothing for now
}
});
$conn->send(json_encode($login));
}, function ($e) {
echo "Could not connect: {$e->getMessage()}\n";
});
}
运行这样的代码也行不通;
$service = new WebsocketService();
$service->getList(44);
echo 'Test';
var_dump($service->getResponse());
因为在我从websocket服务器得到响应之前就出现了“测试”回声。
拜托,赐教!我不确定该搜索什么。
答案 0 :(得分:1)
PHP和websockets似乎仍处于试验阶段。不过,我在medium.com上找到了亚当·温尼帕斯(Adam Winnipass)撰写的精彩教程,该教程对于解决您的问题确实很有帮助:https://medium.com/@winni4eva/php-websockets-with-ratchet-5e76bacd7548
唯一的区别是,他们使用JavaScript而不是PHP来实现其websocket客户端。但是最后应该没有太大的区别,因为一旦我们打开了两端的Websocket连接,两个应用程序都必须发送并也要等待接收通知-这就是它们的显示方式:
创建成功的Websocket连接的一种可能性似乎是扩展MessageComponentInterface
use Ratchet\MessageComponentInterface;
这也需要
use Ratchet\ConnectionInterface;
消息组件接口定义了以下方法:
我认为这是Ratchet库实现它的方式。这就是他们最终启动服务器的方式:
use Ratchet\Server\IoServer;
use MyApp\MyCustomMessageComponentInterface;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new MyCustomMessageComponentInterface()
)
),
8080
);
$server->run();
使用这种体系结构,您已经可以接收(onMessage),也可以使用send()方法发送。
我无法解决您现有代码的确切问题。但是我想,如果您按预期使用库的预构建类和接口(并在此处进行了演示),则应该可以通过将代码添加到相应的方法中来实现所需的功能。< / p>
更多信息和示例可在文档中找到:
答案 1 :(得分:-1)
您是否使用WsServer扩展类,如果您遇到致命错误,这可能是个问题。我不确定你是否会收到致命的错误或警告。另外我注意到公共函数onOpen()打开了一个连接。请尝试参阅此文档http://socketo.me/api/class-Ratchet.WebSocket.WsServer.html可能有用。