PHP を使用してリアルタイム チャット アプリケーションを実装しようとしています。database や file などの永続的なデータストレージを使用せずにそれを行うことは可能ですか? 基本的に必要なのは、PHP で書かれたメディエーターです。
- クライアント ブラウザからのメッセージを受け入れる
- メッセージを他のクライアントにブロードキャストします
- メッセージを忘れる
PHP を使用してリアルタイム チャット アプリケーションを実装しようとしています。database や file などの永続的なデータストレージを使用せずにそれを行うことは可能ですか? 基本的に必要なのは、PHP で書かれたメディエーターです。
html5 のWeb Socketsを確認してください。双方向接続を使用するため、データベースやファイルは必要ありません。サーバーに届いたチャット メッセージは、Ajax 呼び出しなしで他のユーザーのブラウザーに直接送信されます。ただし、Web ソケット サーバーもセットアップする必要があります。
Web ソケットは、多くのリアルタイム アプリケーションでも使用されています。私はまもなくそれに関する完全なチュートリアルを書く予定です。お知らせします。
を使用する必要がありますSockets
。この記事はあなたがやりたいことを正確にカバーします:http://devzone.zend.com/209/writing-socket-servers-in-php/
同じ問題を解決しようとしたとき、Nginx のPush Moduleを使用しました。古いブラウザー (通常は WebSocket をサポートしない) をサポートする必要があり、TCP プロキシの背後にSocket.ioのような適切なソリューションをセットアップする自信がなかったため、この方法を選択しました。
ワークフローは次のようになりました。
/subscriber
クライアントは、すべての人に開かれている私の場所にロング ポーリングを介して接続します。/publisher
場所は、自分のサーバーからの接続のみを受け入れます/publisher
.これをもう一度やり直す必要がある場合は、Comet スタイルのロングポーリングへの適切なフォールバックがあり、クライアント スクリプトとサーバー スクリプトの両方に関する優れたドキュメントがあるため、間違いなく Socket.io ルートに行きます。
お役に立てれば。
PHPがビジネスで必要な場合は、別の言語をミックスに追加すると、2つの問題が発生します。
永続的で常に実行されているデーモン化されたPHPIRCdサーバーを実行することは完全に可能です。私はそれを実行したので、何年も実行されたオンラインゲームを作成することを知っています。
私が使用したIRCサーバーの部分は、WaveIRCdの修正バージョンです: http ://sourceforge.net/projects/waveircd/
ここで利用できるようにしたコードを使用してデーモン化しました: http ://www.thudgame.com/node/254
そのコードはやり過ぎかもしれません:私はそれをできるだけ頑丈に書いたので、PHPのpcntl_fork()を使用してデーモン化を試み、次にバックグラウンドで再帰的に自分自身を呼び出すことにフォールバックし、次にperlにフォールバックします。また、誰かがそれをオンにした場合のPHPのセーフモードのセキュリティ制限、およびcronを介して呼び出されることによって課されるセキュリティ制限も処理します。
おそらく、数行にまとめることができます。「デーモンルール...」というコメントが付いたビット-これらのルールに従ってください。プロセスを正常にデーモン化できます。
予期しないデーモンの停止などを処理するために、cronを介して毎分そのdaemoniserを実行し、デーモンがすでに実行されているかどうかを確認しました。実行されている場合は、静かに停止したか、デーモンが応答しなくなった場合は、デーモンを強制終了しました。その代わりになりました。
IRCは分散型であるため、非常に頑丈で、数か月前にサイトが少し腐敗するまで、数年間はダウンタイムのないマルチプレイヤーブラウザゲームを提供してくれました。フロントエンドをFlashで書き直して、時間があるときにいつか元に戻す必要があります...
(次に、PHPボット用に別のデーモンライザーを実行してゲーム自体を管理し、ゲームをJavaアプレットとして接続し、ボットに話しかけてゲームをプレイしましたが、ここでは関係ありません)。
WaveIRCdは保守されなくなったため、他の誰かがプロジェクトをフォークしてサポートしているかどうかを確認するために、探し回る価値があります。
[2012年の編集:フロントエンドをHTML5 / Javascriptにする場合、またはHTTPが接続するのと同じポートを介して接続する場合は、FlashやJavaを使用する場合よりもオプションが制限されます。その場合は、他の人のアドバイスを受けて、「WebSockets」(現在のほとんどのブラウザーではサポートが不十分)または「Socket.io」プロジェクト(WebSocketsを使用しますが、Flashにフォールバックするか、その他のさまざまな方法を使用します。ブラウザが利用可能です)。
上記は、ホストが別のポートでサービスを実行することを許可している状況の場合です。特に、多くの場合、ToSにIRCdの実行に対する明示的なルールがあります。]
[2019年の編集:WebSocketは現在広くサポートされているので、問題なく使用できます。関連するケーススタディとして、SlackはPHPで記述され(https://slack.engineering/taking-php-seriously-cf7a60065329による)、しばらくの間IRCプロトコルをサポートしていましたが、それ以降は廃止されたと思います。メインプロトコルとして、JSON over WebSockets( https://api.slack.com/rtm )に基づくAPIを使用します。これはすべて、PHP IRCdが、IRCプロトコルが別のプロトコルとの間で変換される場合でも、エンタープライズレベルのパフォーマンスと品質を提供できることを示しています。これにより、パフォーマンスが低下すると予想されます。]
PHP は、(apache-php、fastcgi などの通常のセットアップでは) 要件に適していません。これは、PHP スクリプトが要求ごとに上から下に実行され、外部を使用しないと要求間の状態を維持できないためです。サービスまたはデータベース/ファイル (たとえば、 http://php.net/manual/de/book.apc.phpを除きますが、チャットの実装を意図したものではなく、複数のサーバーに拡張することはできません。)
Node.js、特に Node.js モジュール Socket.IO (A Websocket ライブラリ) を確認する必要があります。それは信じられないほど使いやすく、揺るぎません。Socket.IO は、オプションの redis バックエンドを使用して複数のチャット サーバーにスケーリングすることもできます。つまり、スケーリングが容易になります。
$_SESSION
PHPはセッションデータをファイルに保存するため、静的セッションIDを通信チャネルとして使用しようとしても解決策にはなりません。
データベースやファイルなどの永続的なデータ ストレージを使用せずにそれを行うことは可能ですか?
可能ですが、使用しないでください。データベースまたはファイル ベースは、チャットを遅くしません。これにより、チャット アプリケーションのセキュリティが強化されます。永続データなしで、 ajaxとソケットを使用して Web ベースのチャットを作成できます。
次の投稿が表示されます。
ある種のストレージをバッファーとして使用する必要があります。file または db (これもファイルを使用します) を使用しないことは妥当です。php の共有メモリ関数を使ってみることもできますが、私は有効な解決策を知らないので、最初からやり直す必要があります。
これには node.js サーバーを使用することをお勧めします。WebSockets は現在、クロスブラウザーではありません (完全に機能する node.js の socket.io を除く)。
これを達成するための 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クライアントが接続するには常に実行する必要があります. その後、ソケットに接続する 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);
}
?>
このPHPクライアントにメッセージを投稿するjQueryで呼び出すには、ある種のajaxを使用する必要があります。
http://devzone.zend.com/209/writing-socket-servers-in-php/ http://php.net/manual/en/function.fsockopen.php
あなたはそれがすべてPHPで書かれなければならないとは言いませんでした:)
RabbitMQをインストールしてから、WebSocketとRabbitMQの上に構築されたこのチャット実装を使用します。
あなたのPHPはほとんど「チャットルームクローム」です。ほとんどのサイトがオフラインHTML5コンテンツの5メガの制限内に収まる可能性があり、非常に柔軟な(そしておそらく自分でやった場合よりも堅牢な)チャットシステムがあります。
部屋を出ると、チャット履歴のメッセージも20通あります。
簡単に言えば、できません。現在の HTTP/HTML 実装は をサポートしていないため、pushstate
チャット アプリのアルゴリズムは次のようにする必要があります。
そのため、受信者は常に新しいリクエストを作成し、新しいメッセージが送信されたかどうかを確認する必要があります。(AJAX Callまたは同様のもの)したがって、送信イベントと受信イベントの間に常に遅延があります。
見てみましょう: http://today.java.net/article/2010/03/31/html5-server-push-technologies-part-1
ZeroMQのようなソケットライブラリを調べてみてください。これらはメッセージの即時転送を可能にし、TCPよりも高速で、リアルタイムです。それらのインフラストラクチャにより、データを最初にどこにも保存しなくても、ポイントAとBの間でデータを即座に送信できます(ただし、選択することもできます)。これがZeroMQのチャットクライアントのチュートリアルです
PHP だけを使用する必要がある場合は、チャット メッセージをセッション変数に格納できます。セッションはオブジェクトのように、多くの情報を格納できます。jQuery を使用できる場合は、メッセージが送信された後に段落を div に追加するだけで済みますが、サイトが更新されると、メッセージはなくなります。または組み合わせて、メッセージをセッションに保存し、それをjQueryとajaxで更新します。