17

PHP を使用してリアルタイム チャット アプリケーションを実装しようとしています。database や file などの永続的なデータストレージを使用せずにそれを行うことは可能ですか? 基本的に必要なのは、PHP で書かれたメディエーターです。

  1. クライアント ブラウザからのメッセージを受け入れる
  2. メッセージを他のクライアントにブロードキャストします
  3. メッセージを忘れる
4

14 に答える 14

14

html5 のWeb Socketsを確認してください。双方向接続を使用するため、データベースやファイルは必要ありません。サーバーに届いたチャット メッセージは、Ajax 呼び出しなしで他のユーザーのブラウザーに直接送信されます。ただし、Web ソケット サーバーもセットアップする必要があります。

Web ソケットは、多くのリアルタイム アプリケーションでも使用されています。私はまもなくそれに関する完全なチュートリアルを書く予定です。お知らせします。

于 2012-07-19T13:41:13.477 に答える
6

を使用する必要がありますSockets。この記事はあなたがやりたいことを正確にカバーします:http://devzone.zend.com/209/writing-socket-servers-in-php/

于 2012-07-19T14:36:09.477 に答える
3

同じ問題を解決しようとしたとき、Nginx のPush Moduleを使用しました。古いブラウザー (通常は WebSocket をサポートしない) をサポートする必要があり、TCP プロキシの背後にSocket.ioのような適切なソリューションをセットアップする自信がなかったため、この方法を選択しました。

ワークフローは次のようになりました。

  1. /subscriberクライアントは、すべての人に開かれている私の場所にロング ポーリングを介して接続します。
  2. この/publisher場所は、自分のサーバーからの接続のみを受け入れます
  3. クライアントがサブスクライブして話すとき、基本的には、送信されたデータを処理するように PHP スクリプトに要求するだけです。
  4. このスクリプトは、検証、承認などを実行してから、(curl を介して) メッセージを JSON 形式で/publisher.
  5. Nginx のプッシュ モジュールは、サブスクライバーへのメッセージの返送を処理し、クライアントは新しいロング ポーリング接続を確立します。

これをもう一度やり直す必要がある場合は、Comet スタイルのロングポーリングへの適切なフォールバックがあり、クライアント スクリプトとサーバー スクリプトの両方に関する優れたドキュメントがあるため、間違いなく Socket.io ルートに行きます。

お役に立てれば。

于 2012-07-22T01:38:47.753 に答える
2

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プロトコルが別のプロトコルとの間で変換される場合でも、エンタープライズレベルのパフォーマンスと品質を提供できることを示しています。これにより、パフォーマンスが低下すると予想されます。]

于 2012-07-26T23:37:19.007 に答える
2

PHP は、(apache-php、fastcgi などの通常のセットアップでは) 要件に適していません。これは、PHP スクリプトが要求ごとに上から下に実行され、外部を使用しないと要求間の状態を維持できないためです。サービスまたはデータベース/ファイル (たとえば、 http://php.net/manual/de/book.apc.phpを除きますが、チャットの実装を意図したものではなく、複数のサーバーに拡張することはできません。)

Node.js、特に Node.js モジュール Socket.IO (A Websocket ライブラリ) を確認する必要があります。それは信じられないほど使いやすく、揺るぎません。Socket.IO は、オプションの redis バックエンドを使用して複数のチャット サーバーにスケーリングすることもできます。つまり、スケーリングが容易になります。

$_SESSIONPHPはセッションデータをファイルに保存するため、静的セッションIDを通信チャネルとして使用しようとしても解決策にはなりません。

于 2012-07-21T01:29:17.467 に答える
2

データベースやファイルなどの永続的なデータ ストレージを使用せずにそれを行うことは可能ですか?

可能ですが、使用しないでください。データベースまたはファイル ベースは、チャットを遅くしません。これにより、チャット アプリケーションのセキュリティが強化されます。永続データなしで、 ajaxソケットを使用して Web ベースのチャットを作成できます。

次の投稿が表示されます。

  1. データベースベースのチャットルームは悪い考えですか?
  2. チャット アプリケーションのファイルではなく SQL DB からポーリングすると、パフォーマンスが向上しますか?
  3. チャット メッセージ用のデータベース バッファとして memcached を使用する
  4. PHPの質問の永続データ
  5. https://stackoverflow.com/questions/6569754/how-can-i-develop-social-network-chat-without-using-a-database-for-storing-the-c
  6. チャット アプリでのストレージ効率のためのファイルとデータベース
于 2012-07-20T07:02:58.167 に答える
2

ある種のストレージをバッファーとして使用する必要があります。file または db (これもファイルを使用します) を使用しないことは妥当です。php の共有メモリ関数を使ってみることもできますが、私は有効な解決策を知らないので、最初からやり直す必要があります。

于 2012-07-17T06:48:51.227 に答える
1

これには node.js サーバーを使用することをお勧めします。WebSockets は現在、クロスブラウザーではありません (完全に機能する node.js の socket.io を除く)。

于 2012-07-21T22:56:04.603 に答える
1

これを達成するための 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

于 2012-07-20T13:57:17.543 に答える
0

あなたはそれがすべてPHPで書かれなければならないとは言いませんでした:)

RabbitMQをインストールしてから、WebSocketとRabbitMQの上に構築されたこのチャット実装を使用します。

あなたのPHPはほとんど「チャットルームクローム」です。ほとんどのサイトがオフラインHTML5コンテンツの5メガの制限内に収まる可能性があり、非常に柔軟な(そしておそらく自分でやった場合よりも堅牢な)チャットシステムがあります。

部屋を出ると、チャット履歴のメッセージも20通あります。

https://github.com/videlalvaro/rabbitmq-chat

于 2012-07-25T02:13:44.447 に答える
0

簡単に言えば、できません。現在の HTTP/HTML 実装は をサポートしていないため、pushstateチャット アプリのアルゴリズムは次のようにする必要があります。

  1. A: 送信済みメッセージ
  2. B、C、D: 新しいメッセージが送信されている間に実行して、このメッセージを取得します。

そのため、受信者は常に新しいリクエストを作成し、新しいメッセージが送信されたかどうかを確認する必要があります。(AJAX Callまたは同様のもの)したがって、送信イベントと受信イベントの間に常に遅延があります。

  • つまり、データは db やファイル システムなどのグローバルな場所に保存する必要があります。

見てみましょう: http://today.java.net/article/2010/03/31/html5-server-push-technologies-part-1

于 2012-07-17T06:30:20.870 に答える
-1

ZeroMQのようなソケットライブラリを調べてみてください。これらはメッセージの即時転送を可能にし、TCPよりも高速で、リアルタイムです。それらのインフラストラクチャにより、データを最初にどこにも保存しなくても、ポイントAとBの間でデータを即座に送信できます(ただし、選択することもできます)。これがZeroMQのチャットクライアントのチュートリアルです

于 2012-07-19T06:44:29.697 に答える
-1

PHP だけを使用する必要がある場合は、チャット メッセージをセッション変数に格納できます。セッションはオブジェクトのように、多くの情報を格納できます。jQuery を使用できる場合は、メッセージが送信された後に段落を div に追加するだけで済みますが、サイトが更新されると、メッセージはなくなります。または組み合わせて、メッセージをセッションに保存し、それをjQueryとajaxで更新します。

于 2012-07-17T06:06:01.173 に答える