Страница 1 из 6

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

Добавлено: 2016.11.01, 12:46
girmate
Хочу сделать чат на сайте. Поскольку чат будет на большинстве страниц, значит оформлять буду в виде виджета. Поскольку ранее никогда не строил чаты, прошу вмешаться в ход моих мыслей, чтобы поправить меня, если я я где-то заблуждаюсь.

В чат могут оставлять сообщения авторизованные пользователи, остальные могут только читать. Это задача RBAC и ACF, поэтому эту часть пока не беру во внимание.

Создаем модель:
- количество записей предусматриваем много, поэтому primary_key (id) пусть будет bigint
- конечно же нам нужно знать кто прислал сообщение, добавляем поле user_id (int), где будем хранить id автора сообщения
- собственно, само сообщение text (с типом text)
- дата создания сообщения created_at (int)

Итак, получилась модель
id, user_id, text, created_at
Но, подумав, я решил что пусть в этом чате пользователи могут оставлять личные сообщения. То есть кликают по имени юзера и тогда сообщение видит только тот пользователь, кому оно адресовано.
Добавим в модельку поле for_user(int), где будем хранить id пользователя для кого предназначено сообщение.
Теперь наша модель (пусть это будет Chat) выглядит следующим образом:
id, user_id, for_user, text, created_at
Возможность отправки в общий чат картинок, файлов и прочей лабуды пока исключаем. Чат нам нужен просто для общения "текстом".
Как же мы будем выбирать сообщения. Я думаю что проблем особых нет

Выбрать все записи, где for_user равен равен NULL, либо for_user равен id пользователя просматривающего чат (исключаем чужие сообщения), сортируем по id в обратном порядке, ну и лимит 50 какой-нибудь. Так мы получаем все сообщения которые отправлены в общий чат или лично нам, выбираем последние 50 записей с конца. Конечно же через with подгрузим id-шники пользователей из связанных таблиц

Вроде бы все так пока что?

Еще немного подумав о том, что бывают плохие пользователи, которые хотят флудить и матюкаться. Значит будем их "мутить", то есть лишать права писать в чат на какое-то время.

Добавим в таблицу USER поле mute (int), где будем хранить время окончания мута (например, текущее время + 3600 [1 час] ), и каждый раз проверять его когда пользователь хочет что-то в чат написать. Если в поле стоит время то проверяем, истекло оно или нет и:
- если истекло, то обнуляем это поле в NULL и разрешаем пользователю отправить сообщение
- если не истекло, то пользователь пока не может еще писать в чат
- если поле =NULL - сообщение можно принять и положить в БД (Chat)

Скажите, есть ли у вас замечания по моему ходу мыслей? Буду рад любым комментариям.

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

Добавлено: 2016.11.01, 12:59
girmate
Виджет планирую обернуть Pjax. Виджет будет делать запросы на сервер каждые 3 секунды (ну или около того). Но не совсем понятно как лучше отдавать сообщения.

Вариант 1. Запрашивать все новые сообщения с id большим последнему полученному сообщению, но не старше 1 часа. Таким образом исключаем запрос когда в ответе будут содержатся все 555 сообщений, если вдруг у кого-то "старый" id=1.
Вариант 2. Выбирать все сообщения за последнюю минуту, и отдавать их клиенту, а уже на стороне клиента отсекать те сообщения, которые у него уже имеются. Но тогда много лишних сообщений в выборке, что больше нагрузит сервер.

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

Добавлено: 2016.11.01, 13:07
zelenin
почему не вебсокеты?

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

Добавлено: 2016.11.01, 13:54
girmate
zelenin писал(а):почему не вебсокеты?
Я даже не знаю что это такое, какой профит от этого и насколько это сложнее. [пошел читать]. Нужно на сервере какое-то программное обеспечение дополнительно устанавливать? У меня будет обычный shared-хостинг.

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

Добавлено: 2016.11.01, 14:00
girmate
Немного прочитал про сокеты, пока что понял что это лучшее решение, когда идет частый обмен данных (для чата самое то), а также для систем мониторинга в реальном времени. Но если нужен какой-нибудь node.js, то наверное не получится развернуть на моем хостинге такое? Как это сделать малой кровью?

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

Добавлено: 2016.11.01, 14:02
zelenin
girmate писал(а):Немного прочитал про сокеты, пока что понял что это лучшее решение, когда идет частый обмен данных (для чата самое то), а также для систем мониторинга в реальном времени. Но если нужен какой-нибудь node.js, то наверное не получится развернуть на моем хостинге такое?
google => php websocket chat

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

Добавлено: 2016.11.01, 14:03
girmate
zelenin писал(а):
girmate писал(а):Немного прочитал про сокеты, пока что понял что это лучшее решение, когда идет частый обмен данных (для чата самое то), а также для систем мониторинга в реальном времени. Но если нужен какой-нибудь node.js, то наверное не получится развернуть на моем хостинге такое?
google => php websocket chat
Уже читаю.

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

Добавлено: 2016.11.01, 14:12
girmate
to zelenin. Немного почитал. Есть вопросы. Я смогу запретить пользователю писать в чат? Я смогу помечать сообщения для некоторых пользователей (личные сообщения, которые видит только тот кому они предназначены)? Где хранятся все сообщения? Я смогу посмотреть историю сообщений за прошлый месяц?

P.S. Понятно, что все это можно. Вопрос сколько времени уйдет на изучение). Но штука крутая и я даже не подозревал что такое есть. Точнее название где-то слышал, но не думал что нужно мне.

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

Добавлено: 2016.11.01, 14:19
zelenin
веб-сокет - просто протокол обмена данными клиента и сервера.

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

Добавлено: 2016.11.01, 16:15
girmate
zelenin писал(а):веб-сокет - просто протокол обмена данными клиента и сервера.
Александр, очень благодарен за наводку. Еще только начал изучать. Клиентскую часть посмотрел. Небольшой вопрос: почему так быстро происходит обмен? Что такого лишнего в обычном http, что он отдает данные не так быстро по сравнению с websocket протоколом? Причина в том, что websocket соединение может быть постоянно открыто?

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

Добавлено: 2016.11.01, 16:19
zelenin
girmate писал(а):
zelenin писал(а):веб-сокет - просто протокол обмена данными клиента и сервера.
Александр, очень благодарен за наводку. Еще только начал изучать. Клиентскую часть посмотрел. Небольшой вопрос: почему так быстро происходит обмен? Что такого лишнего в обычном http, что он отдает данные не так быстро по сравнению с websocket протоколом?
это постоянное соединение. а в обычном http (1.1) открываем соединение, передаем данные, закрываем соединение. Что а) медленнее для клиента б) тяжелее для сервера.

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

Добавлено: 2016.11.01, 16:21
girmate
Да, я дополнил свой вопрос, мои предположения совпали с Вашим ответом. Отлично.

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

Добавлено: 2016.11.01, 16:22
girmate
Самое интересное, я раньше ничего не знал про сокеты и часто думал каким образом на сайтах, где есть чат и туда пишут десятки пользователей одновременно - в окне чата обновление происходит почти мгновенно, ведь через ajax нужно время или таймаут. Теперь эта загадка разрешилась благодаря Вам.

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

Добавлено: 2016.11.02, 09:08
sda
girmate писал(а):Самое интересное, я раньше ничего не знал про сокеты и часто думал каким образом на сайтах, где есть чат и туда пишут десятки пользователей одновременно - в окне чата обновление происходит почти мгновенно, ведь через ajax нужно время или таймаут. Теперь эта загадка разрешилась благодаря Вам.
Неа, websocket это относительно новый протокол, приобрел статус RFC только в декабре 2011. Пока еще далеко не все его используют. Просто еще есть Comet это набор различных решений, которые позволяют отправлять данные (push) клиенту через HTTP протокол в режиме реального времени. Например long-polling в фейсбуке или http streaming в vk и telegram.

У long-polling суть в том, что клиент отправляет запрос на сервер и он там висит в цикле и ждет пока не появятся новые данные, как только данные появились они отправляются клиенту и соединение закрывается. Клиент получив данные сразу же открывает новое соединение. Если данные в течение определенного времени (например 20 секунд) не появились, то сервер закрывает соединение по таймауту и клиент сразу же открывает новое соединение.

Плюсы: не нужно постоянно опрашивать сервер отправляя бесполезные запросы на сервер, которые ничего не возвращают.
Минусы: если новые данные сыпятся каждую секунду, то будет довольно много обращений к серверу.

У http streaming суть в том, что клиент отправляет запрос на сервер и он там висит в цикле и ждет пока не появятся новые данные, как только данные появились они отправляются клиенту, но в отличии от long-polling соединение не закрывается и сервер дальше продолжает ждать новые данные и отправлять их клиенту снова и снова. Затем сервер по таймауту (например 20 секунд) закрывает соединение, а клиент в свою очередь открывает новое соединение. В php можно реализовать через сброс системного буфера вывода с помощью функции flush.

Плюсы: те же, что и у long-polling плюс избавляемся от оверхедов на постоянные запросы когда новые данные сыпятся каждую секунду или чаще.
Минусы: web-сервер может буфферизировать данные перед отправкой клиенту, что не приводит к немедленной передачи данных в браузер, поэтому нужно уделить этому внимание и настроить веб-сервер соответствующим образом. Также некоторые версии Internet Explorer отображают данные только после получения 256 байт вывода, поэтому нужно раздувать отправленный пакет данных до этого размера например с помощью пустых пробелов. Но Internet Explorer уже RIP и поэтому на него можно забить, тем более, что эти версии точно также не будут работать и с websocket.

Кроме того есть еще ряд технологий например таких как SSE или внедрение невидимого flash размером 1x1 на страницу через который и организуется прием всех обновлений с сервера.

Это такой небольшой экскурс в историю различных решений для реалтайм веба, что было до появления вебсокетов, которые и сегодня используются в большинстве проектов.

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

Добавлено: 2016.11.02, 10:02
vitalik1183
вебсокет в итоге является самым перспективным решением на сегодняшний день?

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

Добавлено: 2016.11.02, 11:38
girmate
Вчера 12 часов читал документацию. Технология зародилась в черновом варианте с 2009 года (или около того). Поддерживается всеми современными версиями браузеров. И оптимально использовать там где нужна мгновенная и частая двусторонняя передача информации - чат, игры, системы мониторинга и так далее. Я, благодаря Александру, узнал об этой технологии только вчера (ну отстал я, да). Скоро подготовлю несколько ключевых вопросов, попрошу чтобы немного рассказал. Как оказалась, клиентская часть очень проста, все самое сложное - на серверной стороне. Но в своем проекте я уже принял решение работать не только с чатом по протоколу websocket, но и еще в одном месте пригодиться. Решил разработку приостановить до получения более-менее вменяемых знаний, чтобы использовать это в своих проектах.

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

Добавлено: 2016.11.02, 13:48
girmate
to zelenin и всем, кто уже сталкивался с websocket протоколом. Технология великолепная, конечно. После краткого ознакомления появились вопросы общего плана.

1. Как мне на серверном скрипте получить правильный id пользователя. Данным пользователя доверять нельзя. Значит нужен какой-то token или что-то вроде этого?

2. Как мне отправлять сообщения конкретному пользователю (личное сообщение в чат)? Искать его соединение (если я правильно понял) и транслировать туда?

3. Я так понимаю скрипт нужно запускать из консоли. То есть всю работу серверного скрипта я закину в консольный контроллер и запускаю. Так? Насколько я понимаю в консоли нет куков и сессий(или сессии есть?)

Ну вот хотя бы словами опишите что знаете. У меня еще не все сложилось, продолжаю штудировать.

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

Добавлено: 2016.11.02, 13:53
zelenin
girmate писал(а):1. Как мне на серверном скрипте получить правильный id пользователя. Данным пользователя доверять нельзя. Значит нужен какой-то token или что-то вроде этого?

2. Как мне отправлять сообщения конкретному пользователю (личное сообщение в чат)? Искать его соединение (если я правильно понял) и транслировать туда?
google => php websocket chat
girmate писал(а):3. Я так понимаю скрипт нужно запускать из консоли. То есть всю работу серверного скрипта я закину в консольный контроллер и запускаю. Так? Насколько я понимаю в консоли нет куков и сессий(или сессии есть?)
а зачем вам куки и сессия?

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

Добавлено: 2016.11.02, 13:58
girmate
zelenin писал(а):
girmate писал(а):1. Как мне на серверном скрипте получить правильный id пользователя. Данным пользователя доверять нельзя. Значит нужен какой-то token или что-то вроде этого?

2. Как мне отправлять сообщения конкретному пользователю (личное сообщение в чат)? Искать его соединение (если я правильно понял) и транслировать туда?
google => php websocket chat
girmate писал(а):3. Я так понимаю скрипт нужно запускать из консоли. То есть всю работу серверного скрипта я закину в консольный контроллер и запускаю. Так? Насколько я понимаю в консоли нет куков и сессий(или сессии есть?)
а зачем вам куки и сессия?
Да ну Александр! Я вчера 12 часов смотрел. И сегодня еще буду до глубокой ночи смотреть. Но очень мало информации на русском, на английском много непонятно. Но самое ужасное в этой теме, что 90% информации и примеров с уже готовыми расширениями. А мне не нужно расширение. Я хочу от простого - к сложному.

Я уже работал со скриптами-примерами, все получается (типа эхо-сервер). В общем случае - когда всем отдавать одно и тоже - вроде все понятно. Но же не буду личное сообщение От Васи к Пете транслировать всем.
Да еще и непонятно как узнать: где Петя, а где Вася. Мне не нужен код. Словами опишите план действий. Там еще есть ключи, которые генерирует браузер, может это как-то использовать.

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

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