1

チャット クライアントが接続するためのチャット サーバーとして機能する PHP CLI スクリプトを主に作成しています (なぜ PHP でそれを行っているのかは聞かないでください。それは別の話です)。

私のスクリプトは、socket_select() 関数を使用して、ソケットで何かが発生するまで実行を停止します。その時点で、ソケットは起動し、イベントを処理し、次のイベントまで待機します。ここで、30 秒ごとに実行する必要のあるルーチン タスクがいくつかあります (tempban されたユーザーの禁止を解除する必要があるかどうかを確認し、ユーザー データベースを保存し、その他のさまざまなことを行います)。

私が言えることは、PHP には非常に優れたマルチスレッド サポートがまったくないということです。私が最初に考えたのは、ソケットがイベントを生成し、プログラムが再び流れるたびにタイムスタンプを比較することでしたが、サーバーが何時間もアイドル状態のままで、クリーンアップ ルーチンが実行されない可能性があるため、これは非常に一貫性がありません。

PHP pcntl 拡張機能に出会いました。これにより、SIGALRM が送信される時間間隔を割り当て、送信されるたびに関数が実行されます。これは私の問題に対する理想的な解決策のように思えますが、pcntl_alarm() と socket_select() がかなり衝突します。SIGALRM がトリガーされるたびに、ソケット制御コードにあらゆる種類のクレイジーなことが起こります。

私のプログラムはかなり長いので、ここにすべてを投稿することはできませんが、コードに関して何か間違ったことをしているとは思わないので、問題ではありません。私の質問は: SIGALRM を待機中の socket_select() と同じスレッドで処理する方法はありますか? もしそうなら、どのように?そうでない場合、ここで私の代替手段は何ですか?

これが私のプログラムからの出力です。私のアラーム機能は単に「Tick!」を出力します。呼び出されるたびに、いつ何かが起こっているかを簡単に知ることができます。これは、4回ティックを許可した後の出力(エラーを含む)です(サーバーへの実際の接続試行はありませんでした):

[05-28-10 @ 20:01:05] チャット サーバーが 192.168.1.28 ポート 4050 で開始されました

[05-28-10 @ 20:01:05] ファイルから 2 人のユーザーを読み込みました

PHP 通知: 未定義のオフセット: 112 行目の /home/danny/projects/PHPChatServ/ChatServ.php の 0

PHP 警告: socket_select(): [4] を選択できません: 116 行目の /home/danny/projects/PHPChatServ/ChatServ.php でシステム コールが中断されました

[05-28-10 @ 20:01:15] カチカチ!

PHP 警告: socket_accept(): 着信接続を受け入れることができません [4]: 126 行目の /home/danny/projects/PHPChatServ/ChatServ.php でシステム呼び出しが中断されました

[05-28-10 @ 20:01:25] カチカチ!PHP 警告: socket_getpeername() は、パラメーター 1 がリソースであると想定しており、129 行目の /home/danny/projects/PHPChatServ/ChatServ.php で指定されたブール値です

[05-28-10 @ 20:01:25] PHP からのソケット接続の受け入れ通知: 未定義のオフセット: 1 の /home/danny/projects/PHPChatServ/ChatServ.php 行 112

PHP 警告: socket_select(): [4] を選択できません: 116 行目の /home/danny/projects/PHPChatServ/ChatServ.php でシステム コールが中断されました

[05-28-10 @ 20:01:35] カチカチ!

PHP 警告: socket_accept(): 着信接続を受け入れることができません [4]: 126 行目の /home/danny/projects/PHPChatServ/ChatServ.php でシステム呼び出しが中断されました

[05-28-10 @ 20:01:45] カチカチ!

PHP 警告: socket_getpeername() は、パラメーター 1 がリソースであると想定しており、129 行目の /home/danny/projects/PHPChatServ/ChatServ.php で指定されたブール値です

[05-28-10 @ 20:01:45] からのソケット接続を受け入れています

PHP Notice: Undefined offset: 2 in /home/danny/projects/PHPChatServ/ChatServ.php 行 112

4

1 に答える 1

2

pcntl_alarmsocket_select共存できますが、正しく行う方法を認識する必要があります。

特に、socket_select()が待機中にアラームが鳴った場合、アラームが処理された後、 はsocket_select()すぐにエラー表示を返します。エラーは「Interrupted System Call」で、出力に表示されています。そのエラーを具体的に確認し、 を再試行する必要がありますsocket_select()

または、アラームの使用を忘れて、代わりに のタイムアウト機能を使用することもできますsocket_select()。これがtv_secパラメータの目的です。タイムアウトを秒単位で指定します。その後、socket_select()ソケットの準備ができていなくても が戻ります。その後、通常の処理を行うことができます。

于 2010-05-30T10:01:40.113 に答える