В настоящее время я работаю над приложением PHP, которое будет использовать некоторые соединения через веб-сокеты для связи с другой службой.
Чтобы общаться с этой службой веб-сокетов, мы используем Ratchet — библиотеку PHP, основанную на реакции PHP.
Этот фрагмент кода должен отправить и ответить на пару запросов, а после этого должен вернуть информацию в «основной поток».
Пример потока:
HTTP-запрос -> контроллер -> Запускает службу, которая открывает клиент веб-сокета -> клиент веб-сокета разговаривает с сервером -> после его завершения он должен вернуть результат коду контроллера -> вывод контроллера пользователю
У меня проблема в том, что я не знаком с реактивным 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());
Код службы установит для своей переменной «ответ» значение, отличное от нуля, как только это будет сделано. Это явно не работает, потому что метод сна блокирует поток. Кроме того, кажется, что цикл while блокирует ввод-вывод, и реактивный код дает сбой.
Решением было бы открыть новый поток и запустить там код веб-сокета, но я бы не был доволен этим.
Я чувствую, что мне нужно реализовать своего рода «наблюдатель» за процессом веб-сокета, но я не уверен, как это сделать.
Код нашего клиента службы 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());
потому что «тестовое» эхо приходит еще до того, как я получаю ответ от сервера веб-сокетов.
Пожалуйста, просветите меня! Я не уверен, что искать.