kzakhariy
@kzakhariy
PHP Developer

Websocket + Vk Long Poll (PHP+Ratchet)?

Пытаюсь реализовать мгновенный обмен сообщениями (в реальном временни) с VK по long poll, прочитав статью 7vn.ru/blog/2012/09/09/vkontakte-async попытался сделать похожее на PHP.
Когда запускаю php server.php то обмен данными по websocket происходит , но когда я запускаю long polling vk тогда у меня коннект websocket постоянно pending , как-то блокирует соединение по websocket. Но при этом сам vk long poll работает, я вижу что в консоль приходят обновления с вк, Код:

<?php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Session\SessionProvider;
use Symfony\Component\HttpFoundation\Session\Storage\Handler;
use getjump\Vk\Wrapper\LongPoll;
use getjump\Vk\Core;
use getjump\Vk\Model\User as User;

// Make sure composer dependencies have been installed
require __DIR__ . '/vendor/autoload.php';
chdir('../');
require 'vendor/autoload.php';

class Messenger extends getjump\Vk\Wrapper\LongPoll
{
    public function __construct($vk) {
        parent::__construct($vk);
    }
    public function longPolling($connect) {
        $server = $this->getServerData();
        $initial = $this->getConnectionInfo($server);
        $user = new User($this->vk);
        $userMap = [];
        $userCache = [];
        
        /**
         * @param $id
         * @return Model\User
         */
        $fetchData = function ($id) use ($user, &$userMap, &$userCache) {
            if (!isset($userMap[$id])) {
                $userMap[$id] = sizeof($userCache);
                $userCache[] = $user->get($id)->response->get();
            }
            
            return $userCache[$userMap[$id]];
        };
        
        while ($data = $this->guzzle->get($initial)->json(['object' => true])) {
            $server->ts = $data->ts;
            $initial = $this->getConnectionInfo($server);
            if ($data->updates) {
                $connect->send(var_dump($data->updates));
            }
        }
    }
}

class myApp implements MessageComponentInterface
{
    protected $clients;
    protected $vk;
    protected $vkPoll;
    protected $sessid;
    protected $session;
    
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
    public function getSession($sessionId) {
        // Apache server's get_session_info.php
        // Note: restrict access to this path so that remote users can't dump
        // their own session data.
        $opts = array('http' => array('method' => 'GET', 'header' => "Cookie: PHPSESSID=$sessionId\r\n"));
        $context = stream_context_create($opts);
        $json = file_get_contents('http://site.com/get_session_info.php', false, $context);
        $session_data = json_decode($json);
        return $session_data;
    }
    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        $this->sessid = $conn->WebSocket->request->getQuery() ['sessid'];
        $this->session = $this->getSession($this->sessid);
        // var_dump($this->session);
        if ($this->session) {
            $this->vk = getjump\Vk\Core::getInstance()->apiVersion('5.34')->setToken((isset($this->session->vk_msg_token) ? $this->session->vk_msg_token: $this->session->vk_closed_token) );
            $this->messanger = new Messenger($this->vk);
        }
         //  Вот в этом месте блокирует websocket 
        // $this->messanger->longPolling($conn);
    }
    public function onMessage(ConnectionInterface $from, $msg) {}
    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }
}
// Run the server application through the WebSocket protocol on port 8080
$server = new Ratchet\App('SERVER_IP_ADDRESS', 8080, '0.0.0.0');
$server->route('/chat', new myApp, array('*'));
$server->run();


jQuery(document).ready(function($) {
	var sessid = $('.sessid').val();
	var conn = new WebSocket('ws://SERVER_IP_ADDRESS:8080/chat?sessid='+ sessid);
	conn.onopen = function(e) { 
	conn.send('New User connected');
				    };
				});
  • Вопрос задан
  • 1538 просмотров
Пригласить эксперта
Ответы на вопрос 1
kzakhariy
@kzakhariy Автор вопроса
PHP Developer
Выяснил что нельзя запускать вечный цикл в одном процессе, нужно VK long poll запускать в одном процессе, а Websocket запускать во втором , и общаться по tcp протоколу с помощью zeromq.org, пример реализации - socketo.me/docs/push

Но возникает два вопроса:
1) как сделать чтобы много пользователей слушали свои сообщения со своим access_token, через "свой" процесс или демон запущенный.
2) если будет например запущенно 1000 вечных циклов - не ляжет ли сервак, или можно пойди другим путем?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы