Я пытаюсь реализовать приложение чата реального времени, используя PHP. Возможно ли это сделать, не используя постоянное хранилище данных, такое как база данных или файл. В основном мне нужен медиатор, написанный на PHP, который
Вы захотите использовать Sockets
. В этой статье вы найдете именно то, что вы хотите сделать: http://devzone.zend.com/209/writing-socket-servers-in-php/
Вы должны проверить веб-сокеты html5. Он использует двухстороннее соединение, поэтому вам не нужна никакая база данных или файл. Любое сообщение чата, поступающее на сервер, будет напрямую отправлено в другой браузер пользователей без какого-либо вызова Ajax. Но вам также нужно настроить сервер веб-сокетов.
Веб-сокеты также используются во многих приложениях реального времени. Вскоре я планирую написать полный учебник по этому вопросу. Я уведомит вас.
Просто попробовал что-то, чего я никогда не делал раньше, в ответ на этот вопрос. Казалось, что я работаю, но я только один раз проверил его. Вместо использования Socket у меня возникла идея использования общей переменной Session. В основном я заставил Session_id быть одним и тем же значением независимо от пользователя, поэтому все они используют одни и те же данные. Из быстрого теста это работает. Вот что я сделал:
session_id('12345'); session_start(); $session_id = session_id(); $_SESSION['test'] = $_SESSION['test'] + 1; echo "session: {$session_id} test: {$_SESSION['test']} <br />";
Поэтому мой мыслительный процесс состоял в том, что вы могли просто сохранить информацию о чате в переменной Session и заставить всех, независимо от того, кому они должны использовать общий сеанс. Затем вы можете просто использовать ajax для постоянной перезагрузки текущей переменной сеанса и использовать ajax для редактирования переменной сеанса при добавлении сообщения. Также вы, вероятно, захотите установить, чтобы сессия никогда не заканчивалась или имела действительно длительное максимальное время.
Как я уже сказал, я немного поиграл с этим в течение нескольких минут, чтобы посмотреть, будет ли это работать.
Когда я попытался решить ту же проблему, я пошел с Push-модулем Nginx. Я решил пойти этим путем, так как мне пришлось поддерживать старые браузеры (которые обычно не поддерживают WebSockets) и не были уверены в настройке подходящего решения, такого как Socket.io, за прокси-сервера TCP.
Рабочий процесс прошел следующим образом:
/subscriber
, который открыт для всех. /publisher
принимает только соединения с моего собственного сервера /publisher
. Если бы мне пришлось делать это снова и снова, я бы определенно пошел по пути Socket.io, так как у него есть надлежащие резервы для долгого опроса в стиле Comet и имеет отличные документы для сценариев Client и Server.
Надеюсь это поможет.
Вам нужно использовать какое-то хранилище в качестве буфера. Правдоподобно не использовать файл или db (который также использует файл). Вы можете попробовать использовать функции общей памяти php, но я не знаю никаких рабочих решений, поэтому вам придется делать это с нуля.
Можно ли это сделать без использования постоянного хранилища данных, такого как база данных или файл?
Это возможно, но вы не должны использовать. База данных или файл не замедляет чат. Он будет предоставлять дополнительную безопасность вашему чат-приложению. Вы можете сделать веб-чат с помощью ajax и сокетов без постоянных данных.
Вы должны увидеть следующие сообщения:
PHP не подходит для ваших требований (в обычной настройке, такой как apache-php, fastcgi и т. Д.), Потому что скрипт PHP запускается сверху вниз для каждого запроса и не может поддерживать какое-либо состояние между запросами без использования внешних услуг или баз данных / файлов (за исключением, например, http://php.net/manual/de/book.apc.php , но он не предназначен для реализации чата и не будет масштабироваться на несколько серверов).
Вы должны обязательно посмотреть на Node.js и особенно на модуль Node.js Socket.IO (библиотека Websocket). Он невероятно прост в использовании и скалы. Socket.IO также может масштабироваться до нескольких чат-серверов с дополнительным backis-сервером redis, что означает, что его проще масштабировать.
Попытка использовать $_SESSION
со статическим идентификатором сеанса как каналом связи, кстати, не является решением, потому что PHP сохраняет данные сеанса в файлы.
Для этого лучше используйте сервер node.js. В настоящее время WebSockets не являются кросс-браузерами (за исключением socket.io для node.js, который отлично работает)
Если у вас есть потребность в бизнесе для PHP, то добавление другого языка в микс просто означает, что у вас есть две проблемы.
Вполне возможно запустить постоянный, постоянно работающий daemonised PHP IRCd-сервер: я знаю, потому что я сделал это, чтобы сделать онлайн-игру, которая работала годами.
Часть сервера IRC, которую я использовал, представляет собой модифицированную версию WaveIRCd: http://sourceforge.net/projects/waveircd/
Я демоннизировал его с помощью кода, который я сделал здесь: http://www.thudgame.com/node/254
Этот код может быть чрезмерным: я написал его настолько же прочным, насколько я мог, поэтому он пытается демонтироваться с помощью pcntl_fork () PHP, затем возвращается к тому, что он рекурсивно выступает в фоновом режиме, затем возвращается к perl и так далее: it также обрабатывает ограничения безопасности безопасного режима PHP на случай, если кто-то повернет это, и ограничения безопасности, наложенные вызовом через cron.
Вероятно, вы могли бы разбить его на несколько строк: биты с комментариями «Daemon Rule …» – следуют этим правилам, и вы сможете отлично зарекомендовать свой процесс.
Чтобы справиться с любой неожиданной смертью демона и т. Д., Я запускал этот демононер каждую минуту через cron, где он проверял, был ли демон уже запущен, и если это так тихо умер, или если демон был неактуальен, его убили и занял свое место.
Из-за всего распределенного характера IRC он был красиво прочен и дал мне многопользовательскую браузерную игру без простоя в течение нескольких лет, пока бит-гните не съели сайт несколько месяцев назад. Я должен попытаться переписать переднюю часть во Flash и снова получить ее обратно, когда у меня будет время …
(Затем я запустил еще один демон для PHP-бота, чтобы управлять самой игрой, а затем подключил к нему игру как java-апплет и поговорил с ботом, чтобы играть в игру, но это не имеет значения здесь).
Поскольку WaveIRCd больше не поддерживается, вероятно, стоит охотиться, чтобы найти, если кто-то еще разветил проект и поддерживает его.
[Изменить: если вы хотите, чтобы ваш передний конец был HTML5 / Javascript, или если вы хотите подключиться через тот же порт, через который проходит HTTP, ваши варианты более ограничены, чем при использовании Flash или Java. В этом случае возьмите рекомендации других и используйте «WebSockets» (плохая поддержка в большинстве современных браузеров) или проект «Socket.io» (который использует WebSockets, но возвращается к Flash или другим другим методам, в зависимости от того, что браузер доступен).
Вышеуказанное относится к ситуациям, когда ваш хост позволяет вам запускать службу на другом порту. В частности, у многих есть явные правила в их ToS против запуска IRCd.]
в коротком ответе вы не можете. текущая реализация HTTP / HTML не поддерживает pushstate
поэтому алгоритм вашего приложения для чата должен следовать:
поэтому получатели всегда должны сделать новый запрос и проверить, было ли отправлено новое сообщение. (AJAX Call или что-то подобное), поэтому всегда существует задержка между отправленным событием и событием приема.
посмотрите: http://today.java.net/article/2010/03/31/html5-server-push-technologies-part-1
Одним из решений для этого является создание сервера сокетов PHP.
<?php // Set time limit to indefinite execution set_time_limit (0); // Set the ip and port we will listen on $address = '192.168.0.100'; $port = 9000; $max_clients = 10; // Array that will hold client information $clients = Array(); // Create a TCP Stream socket $sock = socket_create(AF_INET, SOCK_STREAM, 0); // Bind the socket to an address/port socket_bind($sock, $address, $port) or die('Could not bind to address'); // Start listening for connections socket_listen($sock); // Loop continuously while (true) { // Setup clients listen socket for reading $read[0] = $sock; for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] != null) $read[$i + 1] = $client[$i]['sock'] ; } // Set up a blocking call to socket_select() $ready = socket_select($read,null,null,null); /* if a new connection is being made add it to the client array */ if (in_array($sock, $read)) { for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] == null) { $client[$i]['sock'] = socket_accept($sock); break; } elseif ($i == $max_clients - 1) print ("too many clients") } if (--$ready <= 0) continue; } // end if in_array // If a client is trying to write - handle it now for ($i = 0; $i < $max_clients; $i++) // for each client { if (in_array($client[$i]['sock'] , $read)) { $input = socket_read($client[$i]['sock'] , 1024); if ($input == null) { // Zero length string meaning disconnected unset($client[$i]); } $n = trim($input); if ($input == 'exit') { // requested disconnect socket_close($client[$i]['sock']); } elseif ($input) { // strip white spaces and write back to user $output = ereg_replace("[ \t\n\r]","",$input).chr(0); socket_write($client[$i]['sock'],$output); } } else { // Close the socket socket_close($client[$i]['sock']); unset($client[$i]); } } } // end while // Close the master sockets socket_close($sock); ?>
с<?php // Set time limit to indefinite execution set_time_limit (0); // Set the ip and port we will listen on $address = '192.168.0.100'; $port = 9000; $max_clients = 10; // Array that will hold client information $clients = Array(); // Create a TCP Stream socket $sock = socket_create(AF_INET, SOCK_STREAM, 0); // Bind the socket to an address/port socket_bind($sock, $address, $port) or die('Could not bind to address'); // Start listening for connections socket_listen($sock); // Loop continuously while (true) { // Setup clients listen socket for reading $read[0] = $sock; for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] != null) $read[$i + 1] = $client[$i]['sock'] ; } // Set up a blocking call to socket_select() $ready = socket_select($read,null,null,null); /* if a new connection is being made add it to the client array */ if (in_array($sock, $read)) { for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] == null) { $client[$i]['sock'] = socket_accept($sock); break; } elseif ($i == $max_clients - 1) print ("too many clients") } if (--$ready <= 0) continue; } // end if in_array // If a client is trying to write - handle it now for ($i = 0; $i < $max_clients; $i++) // for each client { if (in_array($client[$i]['sock'] , $read)) { $input = socket_read($client[$i]['sock'] , 1024); if ($input == null) { // Zero length string meaning disconnected unset($client[$i]); } $n = trim($input); if ($input == 'exit') { // requested disconnect socket_close($client[$i]['sock']); } elseif ($input) { // strip white spaces and write back to user $output = ereg_replace("[ \t\n\r]","",$input).chr(0); socket_write($client[$i]['sock'],$output); } } else { // Close the socket socket_close($client[$i]['sock']); unset($client[$i]); } } } // end while // Close the master sockets socket_close($sock); ?>
с<?php // Set time limit to indefinite execution set_time_limit (0); // Set the ip and port we will listen on $address = '192.168.0.100'; $port = 9000; $max_clients = 10; // Array that will hold client information $clients = Array(); // Create a TCP Stream socket $sock = socket_create(AF_INET, SOCK_STREAM, 0); // Bind the socket to an address/port socket_bind($sock, $address, $port) or die('Could not bind to address'); // Start listening for connections socket_listen($sock); // Loop continuously while (true) { // Setup clients listen socket for reading $read[0] = $sock; for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] != null) $read[$i + 1] = $client[$i]['sock'] ; } // Set up a blocking call to socket_select() $ready = socket_select($read,null,null,null); /* if a new connection is being made add it to the client array */ if (in_array($sock, $read)) { for ($i = 0; $i < $max_clients; $i++) { if ($client[$i]['sock'] == null) { $client[$i]['sock'] = socket_accept($sock); break; } elseif ($i == $max_clients - 1) print ("too many clients") } if (--$ready <= 0) continue; } // end if in_array // If a client is trying to write - handle it now for ($i = 0; $i < $max_clients; $i++) // for each client { if (in_array($client[$i]['sock'] , $read)) { $input = socket_read($client[$i]['sock'] , 1024); if ($input == null) { // Zero length string meaning disconnected unset($client[$i]); } $n = trim($input); if ($input == 'exit') { // requested disconnect socket_close($client[$i]['sock']); } elseif ($input) { // strip white spaces and write back to user $output = ereg_replace("[ \t\n\r]","",$input).chr(0); socket_write($client[$i]['sock'],$output); } } else { // Close the socket socket_close($client[$i]['sock']); unset($client[$i]); } } } // end while // Close the master sockets socket_close($sock); ?>
Вы выполнили бы это, выполнив его через командную строку и всегда должны запускаться для ваших клиентов PHP, чтобы подключиться к нему. Затем вы можете написать PHP-клиент, который будет подключаться к сокету.
<?php $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET / HTTP/1.1\r\n"; $out .= "Host: www.example.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); while (!feof($fp)) { echo fgets($fp, 128); } fclose($fp); } ?>
Вам нужно будет использовать какой-либо тип ajax для вызова с jQuery, отправив сообщение этому PHP-клиенту.
http://devzone.zend.com/209/writing-socket-servers-in-php/ http://php.net/manual/en/function.fsockopen.php
Вы не сказали, что все это должно было быть написано PHP 🙂
Установите RabbitMQ, а затем используйте эту настройку чата, построенную поверх веб-гнезд и RabbitMQ.
Ваш PHP в значительной степени просто «чат-хром». Возможно, большая часть вашего сайта будет вписываться в 5-мегабитный лимит автономного содержимого HTML5, и у вас будет очень гибкая (и, скорее всего, более надежная, чем если бы вы сделали это самостоятельно) чат-систему.
У вас даже есть 20 сообщений истории чата, если вы покинете комнату.
Если вам нужно использовать только PHP, то вы можете хранить сообщения чата в переменных сеанса, сеанс может быть как объект, хранящий много информации. Если вы можете использовать jQuery, тогда вы можете просто добавить абзац в div после отправки сообщения, но затем, если сайт обновлен, сообщения исчезнут. Или комбинировать, хранить сообщения в сеансе и обновлять их с помощью jQuery и ajax.
Попытайтесь найти в библиотеках сокетов, таких как ZeroMQ, они позволяют мгновенно переносить сообщение и быстрее, чем TCP, и в режиме реального времени. Их инфраструктура позволяет мгновенно передавать данные между точками A и B, без сохранения данных в любом месте (хотя вы все равно можете выбрать). Вот учебник для клиента чата в ZeroMQ