Pull to refresh

Пишем свой мессенджер на PHP

Level of difficultyEasy
Reading time6 min
Views7.6K

Эта статья предназначена для тех кто уже знает или начинает учить PHP, Но также человек далёкий от программирования может написать свой мессенджер если просто будет следовать инструкциям.

Для начала давайте объясню что такое WebSocket, простыми словами это тоже самое что и AJAX (http) только тут Клиент (Фронтенду) подключается к Серверу (Бэкенду) и не разрывает соединение а соединение остаётся активным, и мы можем отправлять запросы сколько угодно и сервер тоже. То-есть сервер может на наш запрос не отвечать а мы просто отправлять и наоборот можем вез порядочно отправлять друг другу запросы. Иллюстрация принципа работы WebSocket.

1. Установка PHP

И так мы поняли что такое WebSocket, теперь давайте установим PHP (Язык программирования).

Для Windows пользователей:

Шаг 1: Заходим на официальный сайт ospanel.io.

Шаг 2: Нажимаем скачать и на открывшейся странице два раза нажимаем на кнопку "Нет, спасибо, хочу просто скачать" и начнётся скачивание Open Server (пока скачивайте можете попить чайку 😉)

Шаг 3: Двойной клик по файлу. Откроется окошко с предложением выбрать место, куда распаковать файлы из архива. Я выбрал диск D.

Жмем кнопку ОК. Начнется процесс разархивации.

Шаг 4: Заходим в папку, которую выбрали на 3-ем шаге. Видим что появилась папка OpenServer. Входим в неё.

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

Два раза щелкаем по ярлычку Open Server x64.

Так как это первый запуск Опенсервера, то начнется процесс установки компонентов (MicrosoftVC++) для правильной работы программы.

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

Шаг 5: Заново проходим четвертый шаг – то есть заходим в папку Опенсервера и запускаем программу.

В трее (область в нижнем правом углу там, где часы) видим новый значок – красный флажок.

Щелкаем мышкой по нему, и откроется меню программы.

Шаг 6: Нажимаем My favorites и Git-Bash

Шаг 7(Последний): Пишем на появившейся окошке php -v и видим

Для Linux Пользователей:

Шаг 1: Открываем терминал и пишем команду

Для Arch Linux -> sudo pacman -S php

Для Debiam Linux -> sudo apt -y install php8.2

Для Fedora/RHEL -> sudo dnf install dnf-plugins-core
sudo dnf install http://rpms.remirepo.net/fedora/remi-release-37.rpm
sudo dnf module reset php
sudo dnf config-manager --set-enabled remi
sudo dnf module enable php:remi-8.2
sudo dnf module install php:remi-8.2

Шаг 2 (Последний): Перезагружаем систему и вводим в терминале php -v
Должны увидеть

2. Установка Composer (Пакетный менеджер PHP)

Мы установили PHP, теперь давайте установим Composer чтобы использовать фреймворк Ratchet для написания WebSocket приложений на PHP.

Шаг 1: Зайдите на сайт - https://getcomposer.org/download/ потом спуститесь ниже и нажмите на ссылку Latest Stable у вас должно скачаться файл composer.phar.

Шаг 2: Создайте папку где нибудь в системе для проекта и перемещаем туда скачанный файл composer.phar.

Шаг 3: Открываем терминал и переходим на директорию проекта пишем cd [директория вашего проекта]

Шаг 4: Пишем в терминале php composer.phar require cboden/ratchet для установки фреймворка Ratchet

Теперь у нас всё готово для написания кода.

3. Пишем код

И так давайте в папке проекта создадим файлы client.html и server.php

Вот как должен выглядеть папка нашего проекта после всех выше манипуляций.
Вот как должен выглядеть папка нашего проекта после всех выше манипуляций.

Открываем server.php на любом вам удобном текстовом редакторе (не имеется введу Word или его аналог а именно текстовый редактор по типу блокнота в Windows или редактора кода к примеру Notepad++).

и пишем туда код

<?php

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

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\WebSocket\WsServer;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;

// Создаем класс обработчика сообщений WebSocket
class WebSocketHandler implements MessageComponentInterface {
  protected $clients;

  public function __construct() {
    $this->clients = new \SplObjectStorage;
  }

  // Обработчик нового подключения клиента
  public function onOpen(ConnectionInterface $conn) {
    $this->clients->attach($conn);
    echo "New client connected: {$conn->resourceId}\n";
  }

  // Обработчик получения сообщения от клиента
  public function onMessage(ConnectionInterface $from, $msg) {
	foreach ($this->clients as $client) {
		  $client->send($msg);
	}
  }


  // Обработчик закрытия соединения клиента
  public function onClose(ConnectionInterface $conn) {
    $this->clients->detach($conn);
    echo "Client disconnected: {$conn->resourceId}\n";
  }

  // Обработчик ошибок соединения
  public function onError(ConnectionInterface $conn, \Exception $e) {
    echo "An error has occurred: {$e->getMessage()}\n";
    $conn->close();
  }
}

// Создаем новый WebSocket-сервер на порту 8080
$server = IoServer::factory(
  new HttpServer(
    new WsServer(
      new WebSocketHandler()
    )
  ),
  8080
);

// Запускаем сервер
echo "WebSocket server started\n";
$server->run();

Код require __DIR__ . '/vendor/autoload.php'; запускает автозагрузку библиотек в папке проекта.

Код ниже импортирует фреймворк Ratchet и его элементы.

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\WebSocket\WsServer;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;

а тут
class WebSocketHandler implements MessageComponentInterface {
создаём класс и реализуем интерфейс фреймворка Ratchet MessageComponentInterface к нашему классу WebSocketHandler

protected $clients;
создаём протектированную переменную $clients, эта переменная хранит все подключённые клиенты.

Ниже мы присваиваем к нашей переменной $clients объект SplObjectStorage чтобы мы могли удобно проводить манипуляцию со списком клиентов.

$this->clients = new \SplObjectStorage;

В функции ниже которая запускается при каждом подключений клиента к серверу, добавляется ID клиента к списку $clients и выводится на терминал его ID.

public function onOpen(ConnectionInterface $conn) {
    $this->clients->attach($conn);
    echo "New client connected: {$conn->resourceId}\n";
}

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

  public function onMessage(ConnectionInterface $from, $msg) {
	foreach ($this->clients as $client) {
		  $client->send($msg);
	}
  }

Функция ниже вызывается при разрывании соединения с сервера с клиентом, при этом удаляя его ID из списка $clients.

public function onClose(ConnectionInterface $conn) {
    $this->clients->detach($conn);
    echo "Client disconnected: {$conn->resourceId}\n";
}

Функция ниже вызывается при ошибке с WebSocket, сервер выводит ошибку в терминал и отключает весь сервер.

public function onError(ConnectionInterface $conn, \Exception $e) {
    echo "An error has occurred: {$e->getMessage()}\n";
    $conn->close();
}

В коде ниже создаём хост с портом 8080 если оно не доступно можете изменить на 8081.


// Создаем новый WebSocket-сервер на порту 8080
$server = IoServer::factory(
  new HttpServer(
    new WsServer(
      new WebSocketHandler()
    )
  ),
  8080
);

тут $server->run(); запускаем сервер.

И запускаем код на терминале написав php server.php.

Открываем client.html и пишем туда код

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Chat</title>
</head>
<body>
    <div id="messages"></div>
    <form>
        <input type="text" id="message" autocomplete="off">
        <button>Send</button>
    </form>

    <script>
        const socket = new WebSocket('ws://localhost:8080');

        socket.addEventListener('open', function(event) {
            console.log('Connected to server.');
        });

        socket.addEventListener('message', function(event) {
            const messages = document.getElementById('messages');
            const message = document.createElement('div');
            message.innerHTML = event.data;
            messages.appendChild(message);
        });

        const form = document.querySelector('form');
        const input = document.querySelector('input');

        form.addEventListener('submit', function(event) {
            event.preventDefault();

            const message = input.value;
            socket.send(message);

            input.value = '';
        });
		
    </script>
</body>
</html>

Тут const socket = new WebSocket('ws://localhost:8080'); Создаётся WebSocket соединение с адресом ws://localhsot:8080 с портом 8080 как говорил выше если оно занято можете изменить на 8081.

Функция ниже выполняется при подключений с сервером и выводит текст Connected to server.

socket.addEventListener('open', function(event) {
  console.log('Connected to server.');
});

Функция ниже запускается при каждом получений сообщения которая добавляет в тег с id messages текст сообщения.

socket.addEventListener('message', function(event) {
  const messages = document.getElementById('messages');
  const message = document.createElement('div');
  message.innerHTML = event.data;
  messages.appendChild(message);
});

Функция ниже вызывается при отправке сообщения, которая отправляет сообщение серверу.

 form.addEventListener('submit', function(event) {
  event.preventDefault();

  const message = input.value;
  socket.send(message);

  input.value = '';
});

4. Пользование

Наш мессенджер готов теперь мы можем протестировать его чтобы протестировать открываем на двух вкладках браузера файл client.html и пишем любое сообщение потом нажимаем Enter или кнопку Send.

В продолжений этой статьи мы установим наш мессенджер на хостинг чтобы все могли им пользоваться.

Спасибо за просмотр!

Это моя первая статья и был бы благодарен, если отметите мои ошибки.
С уважением Туленов Темур.
При поддержке сообщества ThinkUP

Only registered users can participate in poll. Log in, please.
Какой Язык программирования вы используйте для программирования с кайфом, то есть для себя ради фана
4.35% Java2
54.35% PHP25
6.52% Rust3
13.04% JS6
2.17% C/C++1
4.35% Assembler2
6.52% C#3
8.7% Свой вариант в комментариях4
46 users voted. 16 users abstained.
Tags:
Hubs:
Total votes 12: ↑4 and ↓8-4
Comments11

Articles