За последние 24 часа нас посетили 72010 программистов и 1650 роботов. Сейчас ищут 914 программистов ...

Сокеты

Тема в разделе "PHP для новичков", создана пользователем Алекс8, 4 ноя 2017.

  1. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    Привет всем) инфы в инете куча, но я решил все таки написать))
    сейчас тут помогаю с одним проектом, мобильное приложение в котором будет чат.. что то типа телеграмма.. и надо все это добро что пишут в мобильном приложении сохранять на сервер..
    понятное дело для этого надо же делать подключения на сокетах..
    я решил слушать сокеты на пхп, но коллега говорит что пхп не умеет создавать несколько потоков, и если поток слушает сокет то он блокируется.. и что лучше сделать на ноде или на чем то другом...
    я то согласен что лучше на надо, но если с пхп я смогу сделать это быстро то с нодой мне надо будет разбираться, потому что мой JS на уровне "повесить на кнопку обработчик"...
    нашел пример, там вот такое вот есть. .
    PHP:
    1. $socket = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
    2. if (!$socket) {
    3.     die("$errstr ($errno)\n");
    4. }
    5. $connects = array();
    6. while (true) {
    7.     //формируем массив прослушиваемых сокетов:
    8.     $read = $connects;
    9.     $read []= $socket;
    10.     $write = $except = null;
    11.     if (!stream_select($read, $write, $except, null)) {//ожидаем сокеты доступные для чтения (без таймаута)
    12.         break;
    13.     }
    14.     if (in_array($socket, $read)) {//есть новое соединение
    15.         //принимаем новое соединение и производим рукопожатие:
    16.         if (($connect = stream_socket_accept($socket, -1)) && $info = handshake($connect)) {
    17.             $connects[] = $connect;//добавляем его в список необходимых для обработки
    18.             onOpen($connect, $info);//вызываем пользовательский сценарий
    19.         }
    20.         unset($read[ array_search($socket, $read) ]);
    21.     }
    22.     foreach($read as $connect) {//обрабатываем все соединения
    23.         $data = fread($connect, 100000);
    24.         if (!$data) { //соединение было закрыто
    25.             fclose($connect);
    26.             unset($connects[ array_search($connect, $connects) ]);
    27.             onClose($connect);//вызываем пользовательский сценарий
    28.             continue;
    29.         }
    30.         onMessage($connect, $data,$info);//вызываем пользовательский сценарий
    31.     }
    32. }
    33. fclose($server);
    насколько я вижу тут можно сколько угодно обрабатывать сокетов.. масив формируется из новых сокетов.. если соединение закрывается то убирает из массива и больше не слушаем этот сокет..
    я правильно понял как тут все работает? или туплю где то?
    Спасибо)
     
  2. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Вы можете развернуть сколько угодно php-FPM процессов которые будут слушать один порт/сокет. Например 300. В условиях работы на php-fpm аргумент твоего товарища имеет актуальность 5-летней давности и мне не понятен.
     
    #2 Zuldek, 4 ноя 2017
    Последнее редактирование: 4 ноя 2017
  3. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    PHP может держать множество соединений на сокеты одновременно. Однако читать
    или писать в один момент времени только в один сокет.
    Можно пробовать параллелить этот процесс с помощью pcntl_fork(). Если будет работать, то это будет очень шустро по сравнению с одним потоком, однако более прожорливо в плане ОЗУ, чем решения на других языках.
     
  4. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Неверно.
    fpm-pool подними который будет смотреть на другой сокет и читай-пиши на здоровье.
    https://gist.github.com/fyrebase/62262b1ff33a6aaf5a54
     
  5. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Я вот сейчас только начал играться с centrifugo, и там очень просто. Установил, конфиги скопипастил, крошечный код на JS, крошечный код на php (с использованием готовой библиотеки), и всё - радуюсь :) Чат с приватными кабинетами (ну почти, без регистрации, id чата в параметре урла, но это в качестве игрушки) собрал за пару часов. https://github.com/centrifugal/centrifugo Теперь сижу и думаю - что боялся её, и зачем пытался веб. сокет на php пилить самостоятельно...
     
    Алекс8 нравится это.
  6. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Неверно именно то, что в цитате?
    --- Добавлено ---
    это же про локальные unix-сокеты, а ТС требует чтобы скрипт обслуживал клиентов извне
     
  7. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Какая хрен разница. Услышь меня: у тебя запускаются разные демоны (!) с какого счастья они не смогут слушать разные локальные порты/сокеты, удаленные?
     
  8. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    где то примеры нашел?? а то я пока застрял на моменте "установил, сгенерил секретный код, а что дальше не понятно..."
     
  9. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Потом берешь пхплибу и передаешь демону сообщения
    Код (Text):
    1. $client = new \phpcent\Client($cent_server);
    2. $client->setSecret($cent_secret);
    3. $client()->publish("public:$channel", $message);
    потом пишешь js-функцию для обработки сообщений, берешь клиентскую либу, подключаешься к центрифуге и подписываешься на канал с назначением своей функции на обработку сообщений.
    Код (Text):
    1. function handleMessage(message) {
    2.    alert('I have a new message!');
    3. }
    4.  
    5. var centrifuge = new Centrifuge({
    6.     // please, read Centrifuge documentation to understand
    7.     // what does each option mean here
    8.     url: 'ws://.../connection/websocket',
    9.     user: user,
    10.     timestamp: timestamp,
    11.     token: token,
    12.     debug: true
    13. });
    14.  
    15. centrifuge.subscribe(chanell, handleMessage);
    Всё!
     
    Алекс8 нравится это.
  10. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Там документация же хорошая, надо просто прочитать всё. ссылки на две php-либы там есть, js-либа описана прямо в доках, конфиг обратного прокси nginx описан в доках. А потом всё, как @[vs] пишет
    --- Добавлено ---
    Ну если хочешь, могу мой мини чат выложить в гитхаб. Он на Slim 3 сделан
     
    Алекс8 нравится это.
  11. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    выложи пожалуйста)) я уже научился отправлять сообщения из вебадминки в браузер)) но этого мало))
    Спасибо
     
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Алекс8 нравится это.
  13. machetero

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

    С нами с:
    25 окт 2014
    Сообщения:
    499
    Симпатии:
    21
    Игорька нет, он центрифугу ещё год назад пиарил.
     
  14. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    https://fzambia.gitbooks.io/centrifugal/content/clients/javascript.html

    прикольно)) центрифуга как бы предназначена больше для того что бы сервер что то отсылал клиенту, а не что бы клиент отсылал что то на сервер..
    а если через сокеты хочется какие то объемы данных слать на сервер с клиента.. например файл изображения отправить надо..
    это что получается лучше использовать что то другое??
     
  15. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    @Алекс8, механизмы отправки чего-то с клиента на сервер у нас и так есть. Для передачи сверхбольших файлов существуют и свои механизмы тоже - закачка файла по частям через HTML5 FileAPI, у примеру. Для этого не нужны веб-сокеты. Проблема именно в том, чтоб передать что-то с сервера на клиент по инициативе сервера, вот её центрифуга решает прекрасно
     
  16. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    А если это андроид мессенжер который должен на сервер отправлять файлы, сообщения.. пусть через post запросы делает?
     
  17. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    А почему бы и не сделать мессанджеру post-запрос?
     
    Алекс8 нравится это.