Создание независимого чата в реальном времени с PHP с помощью сокетов в Symfony 3

Вы можете подумать, что создать чат — это сложная задача, однако это проще, чем вы думаете (как и все, что мы публикуем на этом сайте).

Сокеты традиционно были решением, вокруг которого строится большинство систем чата в реальном времени, обеспечивая двунаправленный канал связи между клиентом и сервером. Это означает, что сервер может отправлять сообщения клиентам. Всякий раз, когда вы пишете сообщение чата, идея заключается в том, что сервер получит его и отправит всем остальным подключенным клиентам.

Замечания: как упоминалось в заголовке, эта реализация независима, и мы охватываем только бэкэнд и основные функциональные возможности на стороне клиента. Это зависит от вас, как настроить его с помощью CSS или других вещей.

Требования

  • Пакет Ratchet Socketome: Ratchet — это слабосвязанная PHP-библиотека, предоставляющая разработчикам инструменты для создания двунаправленных приложений в реальном времени между клиентами и серверами через WebSockets.

Чтобы включить socketome в ваш проект symfony, используйте composer и выполните следующую команду

composer require cboden/ratchet

Или вы можете изменить свой composer.json подать потом использовать composer install,

{
"require": {
"cboden/ratchet": "0.3.*"
}
}

И ты готов к работе!

Создание чата

Чтобы начать с простого чата, мы собираемся создать открытую комнату, доступную для всех (при условии, что WebSocket нацелен на указанный URL).

Шаги, чтобы следовать

  • Создайте класс Chat.php в Sockets папка в вашем комплекте.
  • Создайте команду Symfony в Command папка для запуска чата через командную консоль.
  • Обработайте сокет с Javascript в представлении.
  • Запустите и проверьте свой чат.

Создать сокет

Для начала создайте папку в корневая папка вашего пакета с именем «Sockets» и создайте следующий класс (Chat.php) в теме.

Этот класс будет обрабатывать все соединения, сообщения и т. Д. Это будет использовано позже при инициализации через консоль (не забудьте изменить пространство имен в соответствии с вашим пакетом).

clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}

Теперь, когда у нас есть обработчик сокетов на стороне сервера, нам нужно создать код для его запуска.

Создать команду для запуска чата

Обычно вы должны сохранить код, чтобы запустить его в php-файле, а затем использовать консоль, используя php file.php, Однако, как хорошая практика в Symfony, мы собираемся выполнить этот код в команде Symfony, которая облегчит вам задачу, и вы сможете, если вы захотите выполнять команды в контроллерах или других сумасшедших вещах, которые вы хотите выполнить. делать.

Чтобы продолжить, создайте папку в корневая папка вашего пакета с именем «Command» (если он еще не существует) и создайте следующую команду (SocketCommand.php) на нем .

Не забудьте изменить пространство имен в соответствии с вашим пакетом.

setName('sockets:start-chat')
// the short description shown while running "php bin/console list"
->setHelp("Starts the chat socket demo")
// the full command description shown when running the command with
->setDescription('Starts the chat socket demo')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'Chat socket',// A line
'============',// Another line
'Starting chat, open your browser.',// Empty line
]);
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
}
}

Теперь все на стороне сервера готово и мы сможем начать наш чат, используя php bin/console sockets:start-chat в командной строке, однако нам нужно обработать сокет на стороне клиента.

Обрабатывать сокет на стороне клиента, используя Javascript

Для обработки клиентской части вы можете просто добавить следующий код в вашем представлении. Это довольно просто, как вы можете видеть, он открывает Javascript WebSocket, присоединяет самые основные события и отправляет и получает строку JSON с сервера и на сервер, который обрабатывается на стороне клиента. Не стесняйтесь, чтобы сделать это лучше!

Замечания: зависит от вас, где вы хотите разместить код на стороне клиента. Следующий фрагмент может быть использован, т. Е. В любом представлении ветки или в виде простого html-ответа на любом из ваших контроллеров. Не забудьте изменить URL сокета (в этом случае ws://sandbox:8080 в соответствии с вашим тестовым доменом или localhost).

Public chat
    // This object will be sent everytime you submit a message in the sendMessage function. var clientInformation = { username: new Date().getTime().toString() // You can add more information in a static object }; // START SOCKET CONFIG /** * Note that you need to change the "sandbox" for the URL of your project. * According to the configuration in Sockets/Chat.php , change the port if you need to. * @type WebSocket */ var conn = new WebSocket('ws://sandbox:8080'); conn.onopen = function(e) { console.info("Connection established succesfully"); }; conn.onmessage = function(e) { var data = JSON.parse(e.data); Chat.appendMessage(data.username, data.message); console.log(data); }; conn.onerror = function(e){ alert("Error: something went wrong with the socket."); console.error(e); }; // END SOCKET CONFIG /// Some code to add the messages to the list element and the message submit. document.getElementById("form-submit").addEventListener("click",function(){ var msg = document.getElementById("form-message").value; if(!msg){ alert("Please send something on the chat"); } Chat.sendMessage(msg); // Empty text area document.getElementById("form-message").value = ""; }, false); // Mini API to send a message with the socket and append a message in a UL element. var Chat = { appendMessage: function(username,message){ var from; if(username == clientInformation.username){ from = "me"; }else{ from = clientInformation.username; } // Append List Item var ul = document.getElementById("chat-list"); var li = document.createElement("li"); li.appendChild(document.createTextNode(from + " : "+ message)); ul.appendChild(li); }, sendMessage: function(text){ clientInformation.message = text; // Send info as JSON conn.send(JSON.stringify(clientInformation)); // Add my own message to the list this.appendMessage(clientInformation.username, clientInformation.message); } };

    И ваш общий чат в основном готов к работе.

    Запустите чат и протестируйте его

    Для запуска чата используйте ранее созданную команду в консоли:

    php bin/console sockets:start-chat

    Теперь, если вы только что скопировали код на стороне клиента (разметка и JavaScript), протестируйте его Гугл Хром а также Mozilla Firefox (не обязательно те, но 2 разных браузера), перейдите к своему виду в вашем проекте и увидите магию.

    Чат в реальном времени Symfony 3

    Вы сможете увидеть соединения в консоли, с которой вы начали чат:

    Консольный чат

    Поздравляю! Вы только что сделали простой чат, который можно настроить самостоятельно.

    Несколько чатов

    Предыдущий пример чата ориентирован на корневой путь вашего домена в порту 8080, однако, если ваш чат не предназначен только для одной комнаты, Вы можете создавать разные маршруты сокетов с разными обработчиками.

    В этом случае мы будем использовать тот же Chat.php класс, но обратите внимание, что инициализация отличается, и ваш Команда Symfony должна быть изменена.

    В этом случае вместо ws://sandbox:8080 как маршрут сокета, теперь мы изменим его для ws://sandbox:8080/chat , Теперь наша команда для запуска чата будет:

    setName('sockets:start-chat')
    // the short description shown while running "php bin/console list"
    ->setHelp("Starts the chat socket demo")
    // the full command description shown when running the command with
    ->setDescription('Starts the chat socket demo')
    ;
    }
    protected function execute(InputInterface $input, OutputInterface $output)
    {
    $output->writeln([
    'Chat socket',// A line
    '============',// Another line
    'Starting chat, open your browser.',// Empty line
    ]);
    // The domain of your app as first parameter
    // Note : if you got problems during the initialization, add as third parameter '0.0.0.0'
    // to prevent any error related to localhost :
    // $app = new \Ratchet\App('sandbox', 8080,'0.0.0.0');
    // Domain as first parameter
    $app = new App('sandbox', 8080,'0.0.0.0');
    // Add route to chat with the handler as second parameter
    $app->route('/chat', new Chat);
    // To add another routes, then you can use :
    //$app->route('/america-chat', new AmericaChat);
    //$app->route('/europe-chat', new EuropeChat);
    //$app->route('/africa-chat', new AfricaChat);
    //$app->route('/asian-chat', new AsianChat);
    // Run !
    $app->run();
    }
    }

    Как видите, легко добавить больше маршрутов в порт сокетов, если у вас есть больше классов обработчиков сокетов. Теперь на стороне клиента веб-сокет должен быть теперь:

    var conn = new WebSocket('ws://sandbox:8080/chat');

    Основное устранение неполадок

    Работает локально, но не удаленно или на сервере || Первый пример работает, но несколько маршрутов не

    Это функция безопасности! По умолчанию Храповик связывается с 127.0.0.1 который позволяет только соединения от себя. Рекомендуемый подход заключается в том, чтобы поместить Ratchet за прокси, и только тот прокси (локально) будет подключаться.

    Если вы хотите открыть Ratchet up (не за прокси-сервером), установите третий параметр App равным 0.0.0.0 (как указано в примере).

    Устранение основных неисправностей Ratchet Socketome содержит другие проблемы, которые вы можете найти позже.

    Повеселись !

    Ссылка на основную публикацию
    Adblock
    detector