Отправка сообщения клиенту с помощью веб-сокетов

Я использую https://github.com/orchidsoftware/web-socket в своем проекте laravel и хочу отправлять сообщения подключенным клиентам.

Пока я следил за README и запустил сервер - я получаю предупреждение «Соединение установлено».

Но когда я пытаюсь отправить сообщение клиенту, ничего не происходит. Я создал функцию sendMessageToAll и попытался вызвать ее как из onOpen, так и из другого контроллера:

public function onOpen(ConnectionInterface $conn)
{
    $this->clients->attach($conn);
    $this->sendMessageToAll("message");
}

public function sendMessageToAll($msg){
    foreach ($this->clients as $client) {
        $client->send($msg);
    }
}

И с другого контроллера:

public function test() {
    $ws = new WebSocketClass();
    $ws->sendMessageToAll("testing");
}

Что-то мне не хватает для того, чтобы запустить его?

Есть ли ошибки? Соединение с вашим сервером все еще открыто и активно?

Variable 03.10.2018 22:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
6
1
3 498
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

С другого контроллера? Вы не можете получить доступ к процессу (скрипту php), запущенному в другом потоке (это ваш сервер). Socket-сервер - это концентратор между подключенными клиентами, ожидающий сообщения и, если он получил его, отправляет его снова (если было сказано сделать это). Другими словами - если вы хотите отправить сообщение всем подключенным клиентам, вы должны быть одним из них.


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

Самый простой способ - открыть несколько telnet-соединений с вашим сокет-сервером и начать обмен сообщениями.

public function onOpen(ConnectionInterface $conn)
{
    $this->clients->attach($conn);
    $msg = "Connection established!\n"
    echo $msg;                        // send server log to shell
    sendMessageToAll($msg);           // your initial function should be working
}

public function onMessage(ConnectionInterface $from, $msg) {
    echo "Message from: {$conn->resourceId} received!\n";  //log again
    sendMessageToAll($msg);
}

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

Также отладьте функцию отправки:

public function sendMessageToAll($msg){
    foreach ($this->clients as $client) {
        echo "Sending message to {$client->resourceId} \n";
        $client->send($msg);
    }
}

Теперь откройте несколько соединений telnet с портом сервера сокетов (заметьте в консоли сервера):

telnet 127.0.0.1 8080

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

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

var socket = new WebSocket("ws://localhost");

socket.onopen = function() {
  alert("The connection is established.");
};

socket.onclose = function(event) {
  if (event.wasClean) {
    alert('Connection closed cleanly');
  } else {
    alert('Broken connections'); 
  }
  alert('Key: ' + event.code + ' cause: ' + event.reason);
};

socket.onmessage = function(event) {
  alert("The data " + event.data);
};

socket.onerror = function(error) {
  alert("Error " + error.message);
};


//To send data using the method socket.send(data).

//For example, the line:
socket.send("Hello");

И вам нужно сначала запустить свой сокет-сервер следующим образом:

    Create socket listener:

To create a new listener, you need to

php artisan make:socket MyClass

In the folder app/HTTP/Socket/Listener create template Web listener socket

After creating a need to establish a route which Is located routes/socket.php

//routing is based on an Symfony Routing Component
$socket->route('/myclass', new MyClass, ['*']);

To launch the web-socket, use the command:

php artisan socket:serve

Затем вы следуете авторизации в серверной части, как указано в github.

Да, я сделал это, но как мне отправить сообщение клиенту из серверной части?

Christoffer 05.10.2018 20:44

Ваши onOpen () и sendMessageToAll () отправят сообщение из бэкэнда клиентам. Другой ваш контроллер не нужен. Клиенты будут подключаться к вашему серверу websocket через JS. Ваш sendMessageToAll отправит сообщение при условии, что к вашему серверу сокетов подключены клиенты.

McBern 06.10.2018 03:04

Если вы еще не читали его, существует закрытый вопрос по этой теме, в котором говорится следующее.

you must send a message using php to the working socket. I use Pawl for such purposes.

Вопрос: Как отправить сообщение со стороны сервера? # 11

https://github.com/orchidsoftware/web-socket/issues/11

Я использую расширение Swoole для операций с сокетами, и у меня никогда не было такой проблемы. Просто попробуйте на своих сервисах; https://www.swoole.co.uk/

Другие вопросы по теме