4

Ajax Web アプリケーション、具体的にはゲームを書きたいと思っています。2 つの Web クライアントは、PHP サーバーを介して相互に通信する必要があります。これを解決するための私のアプローチは、クライアントとサーバー、およびサーバーとクライアントの間で Ajax を使用することです。各クライアントは、Ajax を使用して個別のサーバー プロセスを作成します。これら 2 つのサーバー プロセスが、MySQL と名前付きパイプを介して通信するようにしたいと考えています。アプリケーション全体の応答をすぐに取得するには、名前付きパイプが必要です。

最初にパイプを作成し、次にパイプを使用する 2 つのプロセスに分岐する 1 つのサーバー プロセスを使用することはできません。Web アプリケーションは、Web ブラウザーが要求を送信するときにサーバー プロセスを作成します。したがって、名前付きパイプが必要です。各プロセスは、名前付きパイプのファイル名しか知りません。ファイル ハンドルを交換することはできません (少なくとも方法はわかりません)。

私の問題は、同じ関数内で使用されている限り、PHP の方法で名前付きパイプが実際に機能することです。

public function writeAndReadPipe_test(){
    $pipeA = fopen("testpipe",'r+');
    fwrite($pipeA, 'ABCD');

    $pipeB = fopen("testpipe",'r+');
    $content = fread($pipeB, 4);
    echo "[" . $content . "]<br>\n";
}

public function testingPipes_same_function(){
    posix_mkfifo("testpipe", 0777);
    $this->writeAndReadPipe_test();
}

しかし、さまざまな機能を使用すると、fread($pipeB, 4)コマンドはアプリケーション全体をブロックします。

public function writePipe_test(){
    $pipeA = fopen("testpipe",'r+');
    fwrite($pipeA, 'ABCD');
}

public function readPipe_test(){
    $pipeB = fopen("testpipe",'r+');
    $content = fread($pipeB, 4);
    echo "[" . $content . "]<br>\n";
}

public function testingPipes_different_functions(){
    posix_mkfifo("testpipe", 0777);
    $this->writePipe_test();
    $this->readPipe_test();
}

理由を知っている人はいますか?そして、最初のステップで異なる機能間で機能させるにはどうすればよいですか? 2 番目のステップでは、異なるプロセス間でも機能するはずです。リーダーがパイプから読み取る前に、ライターがパイプを閉じるときにも問題が発生することがわかりました。関数が終了すると自動的に閉じると思いますが、これは推測に過ぎません。

PHP の方法がうまくいかない場合は、PHP でコマンド ラインを開き、BASH コマンドを生成して実行させる予定です。これは、Web サーバーが LAMP 環境で動作する限り、どのような場合でも動作するはずです。欠点は、WAMP 環境では機能しないことです。

それで、誰かこれにいくつかのアイデアがありますか?

PS: イベントが送信されるまでリーダーを待機させるには、パイプをブロックする必要があります。私はパイプがノンブロッキングモードで動作できることを知っています

stream_set_blocking($pipe,false);

かそうですが、全体的なアイデアは、イベントが発生するとすぐにリーダーを起動するパイプを使用して、ポーリングせずにそれを行うことです。

4

3 に答える 3

4

名前付きパイプを使用して実際に素晴らしい解決策を見つけたという短い声明:

public function createPipe_test(){
    posix_mkfifo("testpipe", 0777);
}

public function writePipe_test($value){
    $pipeA = fopen("testpipe",'w');
    $valueString = number_format($value);
    $valueLen = number_format(strlen($valueString));
    fwrite($pipeA, $valueLen);
    fwrite($pipeA, $valueString);
}

public function readPipe_test(){
    $pipeB = fopen("testpipe",'r');
    $valueLen = fread($pipeB, 1);
    return fread($pipeB, $valueLen);
}

私は2つのプロセスを持っています。

プロセス 1 が writePipe_test() を呼び出すと、プロセス 2 がreadPipe_test()を呼び出してパイプからデータを読み取るまで待機します 。

プロセス 1 が readPipe_test() を呼び出すと、プロセス 2 がwritePipe_test()を呼び出してパイプに何かを書き込むまで待機します 。

トリックは、'r+' の代わりに 'w' と 'r' です。

于 2013-01-18T16:39:56.817 に答える
1

このように別々の関数でパイプを使用すると、書き込みパイプ A が再び閉じられたり破棄されたりするように見えます ($pipeA のローカル スコープ)。情報を保持するには、パイプを読み取りおよび/または書き込み用に開く必要があると想定されますが、これは本当に理にかなっています。内なる魔法は知らないけど。

また、別のプロセス (echo magic >> testpipe など) からパイプをフィードすると、ブロッキング読み取り呼び出しが成功することも確認できます。したがって、ステップ 2 はすでに完了していますが、パイプハンドルの管理が必要です。

次のように変更すると、動作します。

    private $pipeA;
    public function writePipe_test(){
        $this->pipeA = fopen("testpipe",'r+');
        fwrite($this->pipeA, 'ABCD');
    }

編集: または、$pipeA をグローバル スコープに設定します。

于 2013-01-18T14:11:22.580 に答える
0

2番目の最後の投稿を理解しているかどうかわかりません..

しかし、最後の1つについてコメントすると、誤解していなければ、TCPはさらに複雑になる可能性があります。読み取りまたは書き込みを行う前に接続を確立する必要があるため、オーバーヘッドが異なるためです。

関数の最後で閉じているパイプハンドルに関しては、ソケットで同じ問題に直面すると思います。しかし、パイプファイルは残っています!

永続ストレージ (files,db) を使用すると、クライアントがタイミング的に独立したものになります。ブロッキング呼び出しを使用する場合は、ファイルが実際に使用できる方法になる可能性があります。

于 2013-01-19T02:04:01.240 に答える