За последние 24 часа нас посетили 22699 программистов и 1017 роботов. Сейчас ищут 719 программистов ...

WebSocket Workerman

Тема в разделе "PHP для новичков", создана пользователем AlexProg, 16 апр 2020.

Метки:
  1. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Всем добра!

    Не могу понять почему при попытке отправить приватное сообщение соединение рвётся. Гуглил чаты, каналы... ничего с воркермэеном не нашлось.
    Использую эту либу https://github.com/walkor/Workerman
    Логи чистые, ошибок нет.

    Код сервера:
    PHP:
    1.         if ($toUserId == 0) {
    2.             // Отправляем сообщение всем пользователям
    3.             $messageData['action'] = 'PublicMessage';
    4.             foreach ($connections as $c) {
    5.                 $c->send(json_encode($messageData));
    6.             }
    7.         }
    8.         else {
    9.             $messageData['action'] = 'PrivateMessage';
    10.             if (isset($connections[$toUserId])) {
    11.                 // Отправляем приватное сообщение указанному пользователю
    12.                 $connections[$toUserId]->send(json_encode($messageData));
    13.                 // и отправителю
    14.                 $connections->send(json_encode($messageData));
    15.             }
    16.             else {
    17.                 $messageData['text'] = 'Не удалось отправить сообщение выбранному пользователю';
    18.                 $connection->send(json_encode($messageData));
    19.             }
    20.         }
    Буду благодарен за подсказку/помощь, которая поможет решить проблему.

    Спасибо!
     
  2. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    По этому коду не совсем понятно. Может у вас вообще синтаксическая ошибка. В строке 14 пишете $connections->send(json_encode($messageData));, хотя судя по коду выше $connections это массив объектов, а в строке 18 пишете $connection->send(json_encode($messageData));
     
  3. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Вот начало кода:

    PHP:
    1. $worker->onMessage = function($connection, $message) use (&$connections)
    2. {
    3.     $messageData = json_decode($message, true);
    Ну и

    PHP:
    1. $connections = []; // сюда будем складывать все подключения
     
  4. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    Вы в коде выше пишете
    PHP:
    1. // и отправителю
    2. $connections->send(json_encode($messageData));
    Откуда у массива $connections метод send?
     
    AlexProg нравится это.
  5. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Код с примера, с гитхаба

    PHP:
    1.             // Отправляем сообщение всем пользователям
    2.             $messageData['action'] = 'PublicMessage';
    3.             foreach ($connections as $c) {
    4.                 $c->send(json_encode($messageData));
    5.             }
    PHP:
    1. $worker->onMessage = function($connection, $message) use (&$connections)
    2. {
     
  6. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    В примере с гитхаба объект $connection у которого есть метод send, вы же там где отправляете приватное сообщение, вызываете метод send у массива $connections.

    А вообще что там за сообщения? Обычный чат? Зачем вы отправляете это же сообщение отправителю.
     
    #6 qdevelopment, 16 апр 2020
    Последнее редактирование: 16 апр 2020
    AlexProg нравится это.
  7. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Да, в этом косяк. Заработало! Спасибо большое!

    Осталось понять:
    - как он назначает ID юзерам
    - можно ли указать свои допустим с БД, что бы создавать чат на двоих только. Типо комнаты.
    - почему нельзя отправить сообщение когда человек закрыл чат

    P.S. Куда можно скинуть благодарность? :)
     
  8. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    можно использовать ip пользователя

    вот например когда подключается
    PHP:
    1. $serverIP = gethostbyname(gethostname());
    2.  
    3. $ws_worker = new Worker("websocket://{$serverIP}:2346");
    4.  
    5. $ws_worker->onConnect = function($connection)
    6. {
    7. echo "Клиент " . $connection->getRemoteIp() . " соединился. Дата " . date("Y-m-d H:i:s") . "\n";
    8. };
    9.  
    10. $ws_worker->onClose = function($connection)
    11. {
    12. echo "Клиент " . $connection->getRemoteIp() . " разорвал соединение. Дата " . date("Y-m-d H:i:s") . "\n";
    13. };
     
    AlexProg нравится это.
  9. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    1. Я уже не помню, как там внутри все устроено в Workerman.
    2. Вам нужно использовать базу данных и делать проверки на права отправлять сообщение.
    3. Ну потому что он закрыл чат), некому же отправить. Если вы имеете ввиду, что сообщение пропадает, то вам нужно хранить сообщение в базе.
     
    AlexProg нравится это.
  10. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Для идентификации пользователя? Такое )
    Мне бы привязать к ID в БД
     
  11. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    А когда человек заходит в какую то комнату, заранее созданную кем то в бд:
    PHP:
    1. $ws_worker->onMessage = function($connection, $data)
    2. {
    3.     $get = json_decode( $data, true );
    4.     $ip = $connection->getRemoteIp();
    5.     if(isset($get['entry_room']) ){
    6.        //запись в базу что пользователь $ip вошел в комнату
    7.   }
    8. }
    ну это как вариант, поидее, он же должен войти в чат под каким то ником, и уже должен быть в базе
     
    AlexProg нравится это.
  12. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Базу подключил, всё ок.

    Храню. Как потом отправить при включении?
     
  13. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @webog там много вариантов, экспериментируйте
    --- Добавлено ---
    Смотрите логику.
    1.когда кто то подключается к вебсокету, $ws_worker->onConnect смотрите по ip подключался ли он до этого, какой у него ник, в комнате ли он уже. Если да, то отправляете все клиенту, с его ником, комнатой. Там логика JS уже.
    2. когда кто то новый авторизуется, входит, регистрируется, входит в новые комнаты. Используйте $ws_worker->onMessage. Делайте какие то манипуляции в бд, и возвращайте ответ пользователю.
     
    AlexProg нравится это.
  14. qdevelopment

    qdevelopment Новичок

    С нами с:
    13 окт 2019
    Сообщения:
    41
    Симпатии:
    13
    @webog Чтобы проверять права, когда пользователь авторизуется, создаете для него уникальный токен и при коннекте и отправке сообщений, посылаете этот токен вместе с запросом на сервер.

    По поводу id, вы же сейчас сами назначаете им id? Откуда $toUserId?
    PHP:
    1. // Отправляем приватное сообщение указанному пользователю
    2. $connections[$toUserId]->send(json_encode($messageData));
    --- Добавлено ---
    Он когда снова авторизуется, вы просто показываете ему сообщения. Вебсокет тут не причем.
     
  15. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    С этим не разобрался, криво как-то работает.

    Вот:
    PHP:
    1. $worker->onMessage = function($connection, $message) use (&$connections)
    2. {
    3.     $messageData = json_decode($message, true);
    4.    
    5.     $toUserId = isset($messageData['toUserId']) ? (int) $messageData['toUserId'] : 0;
     
  16. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    AlexProg нравится это.
  17. AlexProg

    AlexProg Активный пользователь

    С нами с:
    13 май 2014
    Сообщения:
    320
    Симпатии:
    7
    Непонятно что это за каналы на другом порте.

    PHP:
    1. $channel_server = new Channel\Server('0.0.0.0', 2206);
     
  18. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Вебсокет запускается на одном порту, это на другом. На клиенте делай подключатся через js именно Channel. Я же говорю пробуй)