morozovsk / websocket

simple php websocket server + demos + yii/yii2 integration + php 7 support
368 stars 74 forks source link

json-post-request, связка Service+Websocket сервер, exceptions #23

Open yshelomentsev opened 8 years ago

yshelomentsev commented 8 years ago

привет! из коробки не работают POST-запросы с JSON-payload, корректно(а может и нет) работает вот такой апдейт GenericSelect (с 99 строки): http://pastebin.com/2M6U3C9v

Так же не очень понятно зачем вызывается колбэк onServiceMessage через каждый перенос строки... Использую, например, service как микро-веб-сервер для обработки входящих запросов с другого сервера и связи их(запросов) с вебсокетами. Так коряво - потому, что, опять же из коробки нельзя получить доступ к подключенным вебсокет-клиентам НЕ из текущего экземпляра компонента, т.е. приходится этих клиентов где-то хранить, апдейтить их статус...

Проблема 3: если пропадает соединение с вебсокет-клиентом, то при попытке ему что-то отослать (sendToClient), сервер падает целиком, не выбрасывая никакого исключения, с точки зрения парадигмы Yii - это не правильно... Обернув stream_select в проверку и try...catch в принципе это решается, но иногда дропает и из других неопределенных мест

morozovsk commented 8 years ago

привет. 1) вот что я нагуглил "Websockets != HTTP. It does not support POST/PUT" а то уже начал вспоминать почему я не делал поддержки пост. Потому что пост идёт в теле, а тело уже кодируется с помощью вебсокет-протокола, а не старым способом. Короче пост и вебсокет не совместимы. можно конечно придумать какой-нибудь грязный хак, но это уже не по стандартам и черевато проблемами в будущем. 2) для вебсокетов используется свой формат обмена сообщениями, но для общения с внутренними скриптами, он мне показался слишком тяжёлым и чтобы ничего не придумывать нового я решил использовать переносы, как знак того, что это конец сообщения. можно конечно делать микровебсервер как у тебя, но мне показалось что достаточно обычных tcp-сокетов, вот пример как можно с другого сервера передать сообщение на вебсокет-сервер: https://github.com/morozovsk/websocket-examples/blob/master/chat3/server/send.php 3) в библиотеке есть код, который отлавливает дисконнекты. видимо до него не успевает дайти очередь, это скорее всего из-за того что высокая нагрузка или обработка происходит слишком медленно. Дело в том, что по-умолчанию используется механизм socket_select, это накладывает ограничения 2к одновременных соединений, а также обработка соединений происходит неэффективно (об этом написано в документации php об этой функции). Чтобы избавиться от ограничений и эффективно работать с соединениями необходимо уставновить расширение event, и указать это в конфиге. Но скорее всего в вашем случае вы сами сохраняете идентификаторы соединений в отдельный массив, но не удаляете из него соединения, которые закрываются. Такие ошибки возникают чаще всего. К сожалению я никак не могу вам помочь не видя вашего кода.

yshelomentsev commented 8 years ago

Спасибо за ответ! По поводу POST - вы абсолютно правы, это я не так использую localsocket. Просто у меня задача как раз связать сокеты и микровебсервис (локальный, принимает локальные http-запросы от оборудования, которые нужно прокидывать сокетами на фронтенд), я почему-то подумал что это и есть оно... Так же снимаю вопрос по поводу множественного срабатывания колбэка - не тот функционал:) Было бы идеально чтобы я мог вызывать компонент Yii и слать ответ конкретному websocket-клиенту, но из коробки это почему-то только для localsocket работает.. т.е. если вручную вызывать компонент (я о Yii, другой инстанс), у него не будет метода sendToClient($clientId, $data, $type), а будет только sendToService, либо я что-то делаю не так и в этом случае:)

А вот по поводу дисконнектов пока вопрос не понятен для меня, код в принципе стандартный - взял Handler из одного из ваших примеров, и туда напихал логики немного. После того как понял, что падает - обернул все, что написал в try..catch-и, но это не помогло. На данный момент пришлось перейти на longpolling, но хотелось бы разобраться в чем дело:) У меня 1-2 соединения на вебсокетах и 1-2rps на входящие в микровебсервис(localsocket), и все локальные, дело не в нагрузке - точно. Попробую перейти на event, отпишусь о результатах.

morozovsk commented 8 years ago

По поводу того как слать конкретному пользователю сообщение из сторонних скриптов, ещё раз оставлю ссылку на пример с реализацией https://github.com/morozovsk/websocket-examples/tree/master/chat3/server если пример не понятен, то могу описать другими словами.

yshelomentsev commented 8 years ago

Наверно я не так объяснил опять - как передать сообщение локальному сокету понятно, но как передать сообщение конкретному подключенному веб-сокету напрямую, без localsocket?

Сейчас использую localsocket только для того, чтобы передавать сообщения конкретным websocket-ам :)

morozovsk commented 8 years ago

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

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