За последние 24 часа нас посетили 68325 программистов и 1651 робот. Сейчас ищут 1022 программиста ...

Идентификация пользователя через сокеты..

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

  1. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    Привет всем)) подскажите как идентифицировать пользователя через сокеты..
    1. Сокет сервер у меня на ПХП (можете кидать тапки)
    2. Клиент как клиент.. создаю соединение вот так вот
    Код (Javascript):
    1.     websocket = new WebSocket(wsUri);
    3. При подключении клиента к серверу получаем что то типа такого
    Код (Text):
    1. $ php server.php
    2. GET /server.php HTTP/1.1
    3. Host: smf2test.ru:9000
    4. Connection: Upgrade
    5. Pragma: no-cache
    6. Cache-Control: no-cache
    7. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
    8. Upgrade: websocket
    9. Origin: http://smf2test.ru
    10. Sec-WebSocket-Version: 13
    11. Accept-Encoding: gzip, deflate
    12. Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,uk;q=0.6
    13. Cookie: PHPSESSID=7f4b1f3662c0a4e69cb8a1fb250bff71
    14. Sec-WebSocket-Key: fHbvcQskj/+QZXR+aaSNwA==
    15. Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
    4. При отправке сообщения серверу мы получаем то что хотим отправить.. тут особо нечего показывать..

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

    Могу ли я использовать Sec-WebSocket-Key? Или лучше ИД сессии?

    У меня на сервере есть массив $clients - где лежат все данные открытых сокетов.. но там ресурсы))
    как это правильно делать?))
    Спасибо) )
     
  2. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Предназначен для другого. Тебе же нужно получить пользователя.
    Для этого есть сессии или authorization bearer. Получаешь пользователя смотришь что ему разрешено и на основании этого уже принимаешь решения подписывать на канал или нет.
    user.1 личное для 1 пользователя
    chat.1 подписка на чат 1
    и т.д
    --- Добавлено ---
    Если на 1 чат разрешено подписываться только админам значит остальных не подписывай если разрешено всем но админам нужна доп инфа значит нужно создать доп канал. И т.д
     
    #2 nospiou, 17 сен 2018
    Последнее редактирование: 17 сен 2018
    Алекс8 нравится это.
  3. Алекс8

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

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

    а насчет допканала не очень понял.. делать еще одно сокет подключение?
    --- Добавлено ---
    ПЫСЫ чего то мой сервер крашится постоянно))
     
  4. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Если ты делаешь на пыхе запросы НА сервер идут по ajax здесь сокеты и не нужны. Сокеты только для приема.
    Просто делаешь кнопку при нажатии на которую отправляется обычный ajax запрос
    Касательно доп канала
    chat.1 - общая инфа (сообщения кто пришел кто ушел и т.д)
    chat.1.admin доп инфа которая приходит только админам.
     
  5. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    о.. а у меня и отправка через сокет соединение)) я просто боюсь что если 300-400 человек начнут писать то аяксом положат сервер..
     
  6. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Пых не асинхронный он так не сможет. Хотя смотря на чем и как делаешь. Тут лучше присмотреться к swoole
    А еще лучше делать все на node например sails.js это как yii но на ноде там и сокеты с коробки и орм и все остальное.
     
    Алекс8 нравится это.
  7. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    насколько я понял он последовательно сокеты опрашивает)) почему через него не принимать?
    отправляю с клиента так..
    Код (Text):
    1.         //convert and send data to server
    2.         websocket.send(JSON.stringify(msg));    
    вроде работает..
     
  8. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    @Алекс8 Сокет сервер у тебя какой?
    Ну адрес клиента это явно не куки сессии, весь вопрос отправить клиенту без его запроса.
     
  9. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    на php написанный.. нашел пример на гите, сейчас допиливаю...
    идентифицирую по PHPSESSID..
    при подключении клиента на сервер передается строка с куками.. оттуда беру PHPSESSID...
    у меня есть массив с клиентами, я ключом делаю значение PHPSESSID.. и потом когда приходит сообщение от какого то клиента - ищу ресурс сокета и смотрю какой там ИД сессии в качестве ключа указан.. .
    как то так...
    по хорошему надо было бы разобраться с нодой)) у меня поверхностные знания JS есть.. но тут сроки поджимают)) так что делаю на том что более менее хорошо знаю))
     
  10. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    А ссылку мог-бы привести? Апач, nginx нужно к этому?
    Идентифицировать это понятно, но идея сокетов отправлять без опроса с клиента.
     
  11. Алекс8

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

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

    PHP:
    1. <?php
    2. $host = 'localhost'; //host
    3. $port = '9000'; //port
    4. $null = NULL; //null var
    5.  
    6. //Create TCP/IP sream socket
    7. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    8. //reuseable port
    9. socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
    10.  
    11. //bind socket to specified host
    12. socket_bind($socket, 0, $port);
    13.  
    14. //listen to port
    15. socket_listen($socket);
    16.  
    17. //create & add listning socket to the list
    18. $clients = array($socket);
    19.  
    20. //start endless loop, so that our script doesn't stop
    21. while (true) {
    22.     //manage multipal connections
    23.     $changed = $clients;
    24.     //returns the socket resources in $changed array
    25.     socket_select($changed, $null, $null, 0, 10);
    26.    
    27.     //check for new socket
    28.     if (in_array($socket, $changed)) {
    29.         $socket_new = socket_accept($socket); //accpet new socket
    30.         $clients[] = $socket_new; //add socket to client array
    31.        
    32.         $header = socket_read($socket_new, 1024); //read data sent by the socket
    33.         perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
    34.        
    35.         socket_getpeername($socket_new, $ip); //get ip address of connected socket
    36.         $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
    37.         send_message($response); //notify all users about new connection
    38.        
    39.         //make room for new socket
    40.         $found_socket = array_search($socket, $changed);
    41.         unset($changed[$found_socket]);
    42.     }
    43.    
    44.     //loop through all connected sockets
    45.     foreach ($changed as $changed_socket) {  
    46.        
    47.         //check for any incomming data
    48.         while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
    49.         {
    50.             $received_text = unmask($buf); //unmask data
    51.             $tst_msg = json_decode($received_text, true); //json decode
    52.             $user_name = $tst_msg['name']; //sender name
    53.             $user_message = $tst_msg['message']; //message text
    54.             $user_color = $tst_msg['color']; //color
    55.            
    56.             //prepare data to be sent to client
    57.             $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));
    58.             send_message($response_text); //send data
    59.             break 2; //exist this loop
    60.         }
    61.        
    62.         $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
    63.         if ($buf === false) { // check disconnected client
    64.             // remove client for $clients array
    65.             $found_socket = array_search($changed_socket, $clients);
    66.             socket_getpeername($changed_socket, $ip);
    67.             unset($clients[$found_socket]);
    68.            
    69.             //notify all users about disconnected connection
    70.             $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
    71.             send_message($response);
    72.         }
    73.     }
    74. }
    75. // close the listening socket
    76. socket_close($socket);
    77.  
    78. function send_message($msg)
    79. {
    80.     global $clients;
    81.     foreach($clients as $changed_socket)
    82.     {
    83.         @socket_write($changed_socket,$msg,strlen($msg));
    84.     }
    85.     return true;
    86. }
    87.  
    88.  
    89. //Unmask incoming framed message
    90. function unmask($text) {
    91.     $length = ord($text[1]) & 127;
    92.     if($length == 126) {
    93.         $masks = substr($text, 4, 4);
    94.         $data = substr($text, 8);
    95.     }
    96.     elseif($length == 127) {
    97.         $masks = substr($text, 10, 4);
    98.         $data = substr($text, 14);
    99.     }
    100.     else {
    101.         $masks = substr($text, 2, 4);
    102.         $data = substr($text, 6);
    103.     }
    104.     $text = "";
    105.     for ($i = 0; $i < strlen($data); ++$i) {
    106.         $text .= $data[$i] ^ $masks[$i%4];
    107.     }
    108.     return $text;
    109. }
    110.  
    111. //Encode message for transfer to client.
    112. function mask($text)
    113. {
    114.     $b1 = 0x80 | (0x1 & 0x0f);
    115.     $length = strlen($text);
    116.    
    117.     if($length <= 125)
    118.         $header = pack('CC', $b1, $length);
    119.     elseif($length > 125 && $length < 65536)
    120.         $header = pack('CCn', $b1, 126, $length);
    121.     elseif($length >= 65536)
    122.         $header = pack('CCNN', $b1, 127, $length);
    123.     return $header.$text;
    124. }
    125.  
    126. //handshake new client.
    127. function perform_handshaking($receved_header,$client_conn, $host, $port)
    128. {
    129.     $headers = array();
    130.     $lines = preg_split("/\r\n/", $receved_header);
    131.     foreach($lines as $line)
    132.     {
    133.         $line = chop($line);
    134.         if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
    135.         {
    136.             $headers[$matches[1]] = $matches[2];
    137.         }
    138.     }
    139.  
    140.     $secKey = $headers['Sec-WebSocket-Key'];
    141.     $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    142.     //hand shaking header
    143.     $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    144.     "Upgrade: websocket\r\n" .
    145.     "Connection: Upgrade\r\n" .
    146.     "WebSocket-Origin: $host\r\n" .
    147.     "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
    148.     "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    149.     socket_write($client_conn,$upgrade,strlen($upgrade));
    150. }
    --- Добавлено ---
    да.. но мне надо понимать что за клиент соединился с сервером..
    если это AJAX запрос то тут вопросов нет.. все видно кто что прислал...
    а с сокетами мне пока не понятно... тут соединение и при инициализации которого отправляется заголовок с куками.. а потом просто текст ходит и все.. и никаких больше заголовков))
     
  12. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    Теперь понятно почему сервер крашится постоянно :)
    Я думаю лучше что-то посолиднее, есть же там свули, центрифуги ....
     
  13. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    уже не крашится)) там проверок не было)) писало в сокеты в которые нельзя писать)) поэтому крашился))
    а так то уже стабильно работает))
     
  14. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    обязательно покрашится...
    если именно на пыхе -
    Ratchet - PHP WebSockets
    смотри
     
  15. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    почему?))

    я сейчас worker смотрю)) но искренне не понимаю почему те 50 строк кода должны покрашится))
    пока вроде работает стабильно))
     
  16. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    я тебе больше скажу, даже одна строка будет в цикле ....
    PHP:
    1. while(true)
    или ни одной - покрашится... вопрос времени
     
  17. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    уже полдня крутится.. норм..
    кстати Worker тоже на php))
    почему им пользуются и не крашится?
     
  18. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Я вот присматривался к экстеншину но им как то никто не пользуется никто его не советует. В той же ларке сервер на ноде поднят. Интересно в итоге узнать за результат. Можно доку глянуть http://fi2.php.net/manual/en/book.sockets.php Кто его знает как там все устроено.
     
  19. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Я вот когда начинал делать проект долго выбирал между ларкой и sails. С одной стороны для пыха все есть все продумано но везде костыли с другой нода для которой все есть без костылей но не до конца продумано. Даже сейчас довольно сомнительный выбор. В 10 ноде вреди mjx планируют добавить плюс декораторы если sails перепишут вообще прикольно будет
     
  20. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    мне честно говоря синтаксис не нравится JS)) на код смотрю и он не красивый какой то))
    если в пхп все по класса разложено)) все понятно))) автозагрузка)) то в JS как то все вечно одной портянкой))
     
  21. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    @Алекс8 Ну потому я и говорю за mjs* с импортами с классами и т.д плюс с появлением async не все так плохо стало. В sails все c коробки на async. Тот же react давно на классах а нода все тормозит.
    А в остальном синтаксис прикольный можно все в одну строку писать:)
     
    #21 nospiou, 18 сен 2018
    Последнее редактирование: 18 сен 2018
  22. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ну справедливости ради, в NodeJS поддерживается последний стандарт JavaScript, а там и классы есть, и модули.
    --- Добавлено ---
    @Алекс8, php в один поток твой сервер выполняет по дефолту. Будет побольше нагрузка - будет трындец котёнку. Одного-то тебя, ясное дело, выдержит. Если swoole какую-нибудь прикрутить, там учтено это должно быть (она, в принципе, php в ноду практически превращает, насколько я понял).
     
    Алекс8 нравится это.
  23. Алекс8

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

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    я вот это https://github.com/walkor/Workerman уже запустил)) научился уже обмениваться соощениями) в две стороны)
     
  24. nospiou

    nospiou Старожил

    С нами с:
    4 фев 2018
    Сообщения:
    3.400
    Симпатии:
    510
    Все это вопрос эстетики в js изначально все объект синтаксис es6 тоже не плох
    Код (Javascript):
    1. module.exports = {
    2.   index: function (req, res) { ... },
    3.   show: function (req, res) { ... },
    4.   store: function (req, res) { ... },
    5. };
    Или даже так
    Код (Javascript):
    1. module.exports = {
    2.   index: (req, res) => { ... },
    3.   show: (req, res) => { ... },
    4.   store: (req, res) => { ... },
    5. };
    С es2015 еще веселее..
     
  25. keren

    keren Новичок

    С нами с:
    15 ноя 2017
    Сообщения:
    513
    Симпатии:
    42
    А останавливать только перезагрузкой? :)
    Там же кодируется какая-то информация - имя, цвет и тп, не просто же текст приходит?