Создаю чат. WebSocket.

Темы, не касающиеся фреймворка, но относящиеся к программированию в целом.
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение zelenin »

girmate писал(а):Видео на yuotube мне "очень" нравится (от Специалиста, например). Смотрим 1-й урок - все замечательно, понятно. Включаю второй - бац,- "а давайте скачаем расширение для серверной части". Накуя мне твое расширение, спрашивается??? И так во всех роликак Там Ratcher, а там на базе Node.js и там еще на чем-то. Чуть накопал на голом PHP.
собираешься сам реализовывать вебсокет-сервер?
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Так а в чем сложность? Если я запустил скрипт с эхо-сервером (отправляет все, что ему прислали) , значит можно и посложнее. Мне же пока не нужно бинарные данные гонять туда-сюда (пока что).
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Здесь был скрипт, но я перешел на другую реализацию.
Последний раз редактировалось girmate 2016.11.02, 17:07, всего редактировалось 1 раз.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Здесь был код, но я перешел на другую реализацию. Позже выложу что получилось.
Последний раз редактировалось girmate 2016.11.02, 17:08, всего редактировалось 1 раз.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Вот думаю как решить те вопросы, которые я сегодня задавал.
Последний раз редактировалось girmate 2016.11.02, 17:08, всего редактировалось 1 раз.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Чтобы понять, как организовать приватные сообщения в чате (от Васи к Пете) мне нужно знать может ли сервер транслировать на определенный сокет (на конкретного пользователя).
Варианты ответов:
а) никогда не может, трансляция всегда идет общим потоком. Все пользователи сразу получает все сообщения от сервера.
б) может, если это организовано на стороне сервера
в) он всегда транслирует на определенные сокеты, перебирая весь массив, поэтому все пользователи из этого массива получают сообщения.
г) другое... (укажите)

Ну буду по одному вопросу спрашивать. Иначе не осилю никогда.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Ммм. Уже лучше. Пошел дальше доки изучать. Жаль, что тема узкоспециализированная, мало людей, которые могут посоветовать, что-то дельное. Пока один Александр, но ему не разорваться. И на том спасибо.
Осторожно! Вы общаетесь с новичком ;)
Onotole
Сообщения: 1808
Зарегистрирован: 2012.12.24, 12:49

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение Onotole »

https://github.com/morozovsk/websocket-examples
Посмотри как тут в примерах сделано
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. Выкладываю свой ход мыслей. WebSocket.

Сообщение girmate »

Посмотрю, спасибо.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

Вот код сервера в который я пытаюсь вникнуть:

Код: Выделить всё

<?php
$host = 'localhost'; //host ws://127.0.0.1:8889
$port = '8889'; //port
$null = NULL; //null var
set_time_limit(0);

// Create TCP/IP sream socket
// Создаёт сокет (конечную точку для обмена информацией)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

// reuseable port
// Устанавливает опции для сокета
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

// bind socket to specified host
// Привязывает имя к сокету
socket_bind($socket, 0, $port);

// listen to port
// Прослушивает входящие соединения на сокете
socket_listen($socket);

//create & add listning socket to the list
//
$clients = array($socket);

//start endless loop, so that our script doesn't stop
while (true) {
    //manage multipal connections
    $changed = $clients;
    //returns the socket resources in $changed array
    // Runs the select() system call on the given arrays of sockets with a specified timeout (PHP Doc)
    socket_select($changed, $null, $null, 0, 10);

    //check for new socket
    if (in_array($socket, $changed)) {
        $socket_new = socket_accept($socket); //accpet new socket
        $clients[] = $socket_new; //add socket to client array

        $header = socket_read($socket_new, 1024); //read data sent by the socket
        perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake

        socket_getpeername($socket_new, $ip); //get ip address of connected socket
        $response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' connected'))); //prepare json data
        send_message($response); //notify all users about new connection

        //make room for new socket
        $found_socket = array_search($socket, $changed);
        unset($changed[$found_socket]);
    }

    //loop through all connected sockets
    foreach ($changed as $changed_socket) {

        // check for any incomming data
        // Получает данные из подсоединённого сокета
        // Полученные данные будут переданы в переменную, указанную в параметре buf.
        // Если происходит ошибка, если соединение сброшено, или если данные недоступны, параметр buf будет установлен в NULL.
        while (socket_recv($changed_socket, $buf, 1024, 0) >= 1) {
            $received_text = unmask($buf); //unmask data
            $tst_msg = json_decode($received_text); //json decode
            $user_name = $tst_msg->name; //sender name
            $user_message = $tst_msg->message; //message text
            $user_color = $tst_msg->color; //color
            //echo $user_color.PHP_EOL;

            //prepare data to be sent to client
            $response_text = mask(json_encode(array('type' => 'usermsg', 'name' => $user_name, 'message' => $user_message, 'color' => $user_color)));
            send_message($response_text); //send data
            break 2; //exist this loop
        }

        $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
        if ($buf === false) { // check disconnected client
            // remove client for $clients array
            $found_socket = array_search($changed_socket, $clients);
            socket_getpeername($changed_socket, $ip);
            unset($clients[$found_socket]);

            //notify all users about disconnected connection
            $response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' disconnected')));
            send_message($response);
        }
    }
}
// close the listening socket
socket_close($socket);

function send_message($msg)
{
    global $clients;
    foreach ($clients as $changed_socket) {
        @socket_write($changed_socket, $msg, strlen($msg));
    }
    return true;
}


//Unmask incoming framed message
function unmask($text)
{
    $length = ord($text[1]) & 127;
    if ($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    } elseif ($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    } else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = "";
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i % 4];
    }
    return $text;
}

//Encode message for transfer to client.
function mask($text)
{
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);

    if ($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif ($length > 125 && $length < 65536)
        $header = pack('CCn', $b1, 126, $length);
    elseif ($length >= 65536)
        $header = pack('CCNN', $b1, 127, $length);
    return $header . $text;
}

//handshake new client.
function perform_handshaking($receved_header, $client_conn, $host, $port)
{
    $headers = array();
    $lines = preg_split("/\r\n/", $receved_header);
    foreach ($lines as $line) {
        $line = chop($line);
        if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) {
            $headers[$matches[1]] = $matches[2];
        }
    }

    $secKey = $headers['Sec-WebSocket-Key'];
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    //hand shaking header
    $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
        "Upgrade: websocket\r\n" .
        "Connection: Upgrade\r\n" .
        "WebSocket-Origin: $host\r\n" .
        "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n" .
        "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn, $upgrade, strlen($upgrade));
}

Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

Вот как понять что конкретный сокет принадлежит конкретному пользователю и как ему (и только ему) туда что-то записать? Половину кода смог расшифровать, половину не совсем понимаю. Поэтому не знаю какие строки смотреть. Подскажите, пожалуйста.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

Одно дело когда пользователь отправил сообщение. Я могу видеть кто отправил и кому он хочет его передать. Но я не знаю как найти того кому нужно передать это сообщение... Он же молчит. Если бы у ресурсов были какие-нибудь метки типа как в ассоциативном массиве. Я бы их перебрал или нашел и отправил персональное сообщение. Может где-то в коде, где происходит "рукопожатие" это делать? Не могу пока что понять реализацию.
Последний раз редактировалось girmate 2016.11.02, 21:08, всего редактировалось 1 раз.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Создаю чат. WebSocket.

Сообщение vitalik1183 »

ребят, скажите, а чем нода не устраивает? зачем эти костыли с пыхом, который априори для этого не создан?
Yii2!
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

vitalik1183 писал(а):ребят, скажите, а чем нода не устраивает? зачем эти костыли с пыхом, который априори для этого не создан?
Потому что я ничего не понимаю в ноде. :)
Последний раз редактировалось girmate 2016.11.02, 21:07, всего редактировалось 1 раз.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

И хот PHP и не создан, но все работает.
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Создаю чат. WebSocket.

Сообщение vitalik1183 »

если честно - самому интересно читать этот топег. про вебсокеты конечно знал. но столкнувшись с нодой - понял что пых остался в прошлом(для постоянных конектов).
Yii2!
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

Можно вкратце, в чем ее преимущества? И что, PHP можно вообще выкинуть чтоли? Или конкретно по этой теме он сильно уступает?
Осторожно! Вы общаетесь с новичком ;)
Аватара пользователя
vitalik1183
Сообщения: 1675
Зарегистрирован: 2014.07.01, 08:42

Re: Создаю чат. WebSocket.

Сообщение vitalik1183 »

пых это серверная вещь, нода это жс на стороне сервера. нет, почему, пых пиздато справляется со своими задачами, но вот реальный кейс. недавно пришлось парсить сайт где было куча аякса и жс. на ноде решался вопрос в 5 строчек кода, на пыхе это практически нерешаемо было бы ибо как выполнять жс и аякс - нипанятно. нода из коробки запускается и висит демоном, пых такое не умеет(по своей природе, только костыли). для чата вам нужна нода. минимум ресурса - максимум эфект. это я про серверную часть. ну а общаться можете и через вебсокеты спокойно(как технология) но серверная часть будет реализована вкуснее, а не кривой while(true){...}
Yii2!
Аватара пользователя
girmate
Сообщения: 1534
Зарегистрирован: 2015.10.27, 12:52

Re: Создаю чат. WebSocket.

Сообщение girmate »

Понял. Спасибо. Собственно а можно ли ноду развернуть на обычном shared-хостинге? И как нода будет взаимодействовать с yii? Или yii тоже неприменим становится если использовать ноду?
Осторожно! Вы общаетесь с новичком ;)
Ответить