3

環境 :

私は、ソケット接続と着信データをリッスンするメインループが明らかにあるDAEMONとして実行するPHP Websocketサーバー(ここsleep(x_number_of_seconds);)を作成しています。サーバー全体。

接続されたクライアントソケットにデータを送信するには、サーバークラスのスコープ内にいる必要があるため、CRONジョブで外部スクリプトを実行したり、新しいプロセスをフォークしたりすることはできません(推測)。

PHP でこれを達成するための魔法のトリックを知っている人はいますか? :/

いくつかのクレイジーなアイデア:

  1. で最後のループ実行時間を追跡し、microtime(true)それを各ループの現在の時間と比較します。それが希望する X 秒間隔の場合、メソッドを実行します...非常に酔って一貫性のない間隔ループが発生します。
  2. setInterval()Websocket を介してサーバーと通信するJavaScriptをブラウザーで実行し、メソッドを実行するように指示します...クレイジーなアイデアがどこにあると言いましたか!

私が達成しようとしていることに関する追加情報:

X 秒ごとに動作を更新する NPC を追加したい小さなオンライン ゲーム (RPG のようなもの) を作成しています。

これを達成する他の方法はありますか?何か不足していますか?Node.js でサーバーを書き直す必要がありますか??

助けてくれてありがとう!

4

2 に答える 2

2

完璧な代替案は存在しないので、クレイジーなソリューション #1 を使用します。

$this->last_tick_time = microtime(true);
$this->tick_interval = 1;
$this->tick_counter = 0;

while(true)
{
    //loop code here...

    $t= microtime(true) - $this->last_tick_time;

    if($t>= $this->tick_interval)
    {
        $this->on_server_tick(++$this->tick_counter);
        $this->last_tick_time = microtime(true) - ($t- $this->tick_interval);
    }
}

基本的に、最後のサーバー ティックからの経過時間が目的のティック間隔以上である場合は、on_server_tick()メソッドを実行します。そして最も重要なことは、時間オーバーフローを差し引いて、これが遅すぎた場合に次のティックがより速く発生するようにすることです。このようにしてギャップを埋め、最後に、socket_selectタイムアウトが 1 秒に設定されている場合、1.99999999+ 秒を超えるギャップが発生することはありません。

また、ティックカウンターも追跡します。このようにして、モジュロ (%) を使用して、次のように複数の間隔でコードを実行できます

protected function on_server_tick($counter)
{
    if($counter%5 == 0)
    {
        // 5 seconds interval
    }

    if($counter%10 == 0)
    {
        // 10 seconds interval
    }
}

私のすべてのニーズをカバーしています!:D

PHP を心配する必要はありません。Node.js に置き換えるつもりはありません。あなたは今でも私の友人です。

于 2013-07-17T03:21:43.440 に答える
0

使用している websocket-framework が原始的すぎて、クライアントからの接続を待っている間にサーバーが他の有用なことを実行できないように思えます。PHP の socket_select() 関数への唯一の呼び出しは、1 秒のタイムアウトにハードコードされており、時間切れになると何もしません。コールバックまたは外部ループを許可する必要があります。

http://php.net/manual/en/function.socket-select.phpマニュアル ページを見てください。最後のパラメータはタイムアウト時間です。socket_select() は、ソケットで着信データを待機するか、タイムアウト時間が経過するまで待機します。これは、やりたいことのように聞こえますが、ライブラリにはそれに対する準備がありません。次に、core/classes/SocketServer.php でライブラリがそれをどのように使用しているかを見てください。

run() を呼び出すと、ソケットでメッセージを取得するまで呼び出し元のコードに戻らないため、何もできないと想定しています。

于 2013-07-16T04:20:03.543 に答える