ホームページ >バックエンド開発 >PHPチュートリアル >ソケット開発に関するいくつかの質問

ソケット開発に関するいくつかの質問

WBOY
WBOYオリジナル
2016-06-23 13:33:20974ブラウズ

最近、WebSocket を使って、携帯電話を PPT リモコンとして使用して、WEB スライドを上下に制御し、会議で自分の内容を説明する、小さなゲームサーバーのようなものを作成することを計画しています。まだ詳しくはありませんが、アドバイスをいただきたい質問がいくつかあります。

1. 損失の問題: 私が学んだことによると、PHP はソケットの観点から PHP スクリプトを開始します。 Web リクエストは一瞬ですが、ほぼ無限ループで実行され、リスニング ポートが繰り返し実行されます。私が見つけたコード例と同様に、while(true) を使用します。 ) スクリプトが最後まで実行されたときにスレッドを破棄せずに継続的な監視を実装するロジック。この秒間で何回実行できますか? この効率は本当に問題ですか?これは、無限ループを実現する唯一の方法です。おそらく、偽装無限ループを実現するのと似ていますが、実際には、CPU を大量に消費することになります。スリープを追加すると、たとえ 1 秒スリープしても応答が遅くなり、ユーザー エクスペリエンスは確実に悪くなるため、高頻度のモニタリングが必要になる可能性があります。


2. プロセス制御の問題:大規模な同時実行については話さないでください。私たちの小規模なプロジェクトでは、php の server.php コマンドを通じてサーバー上でリアルタイム機能を提供しているだけです。聞いていますが、サーバーをシャットダウンしたい場合はどうすればよいですか? これは、php server.php -k stop などではなく、新しいスレッドをトリガーします。アップグレードまたは移行、それを停止するにはどうすればよいですか?
プロセスを検索し、PID を見つけて、それを強制終了します。ただし、Web ディレクトリ内にindex.php をトリガーする他の http リクエストがある場合、それも php プロセスになります。そうですね、大量の php プロセスを見つけた場合、どのプロセスが server.php スクリプトの pid であるかをどのように特定すればよいでしょうか? そうですね、愚かな方法はそれらをすべて強制終了することです... あはは、笑わないでください。私もそうしたくありません。これは、値 1 のクローズ ファイルを生成することで実現できると想像しているからです。server.php がリッスンするたびに、最初にこのファイルを開いて値が 0 かどうかを確認します。そうでない場合は終了します...しかし、このIO損失は間違いなく不合理です、はい、もう一度考えます、もう一度考えます...何も思いつきません、それはすべて愚かな方法です、マスター。 ...


3. メモリの問題: 複数のソケット クライアントがサーバーに接続されています。 最後に、サーバーは以前の server.php プロセスを使用して処理します。新しいプロセスは開始されませんが、元のプロセスがデータをリッスンします。したがって、リスニング関数で配列を作成すると、IP を追加するだけで、多くの人が来ると、長時間実行すると、数十個の IP が存在すると推定されます。もちろん、切断時に配列要素を削除する必要がありますが、これは、すべてのクライアントの処理が 1 つの共有プロセスの下にあるように見えます。例えば、特定の条件下でユーザーAがユーザーBのHPを減らしたり、お金を減らしたりするため(トランザクション機能など)、ユーザーの数が増えると、これらのものを保存するために変数を使用することはできなくなりました。キャッシュを見つける必要があります。


4. 計画の問題: 要件は少し異なります。たとえば、これはリアルタイム チャット ルームですが、私たちの Web サイトは元々通常の Web サイトには、通常の HTTP リクエストによって返される HTML コードによってレンダリングされるページがたくさんありますが、この機能は 53 のカスタマー サービス プラグインと同様に、ほぼすべてのページが開かれます。 、ロードするたびにサーバーに接続する必要があります。ユーザーが新しいウィンドウを開いて古いウィンドウが閉じていない場合があるため、フロントエンドに関しては、これを保存できるかどうか疑問です。リソースを見てみましょう。クリックしないとカスタマー サービスに接続できないようです。ただし、ユーザーが新しいページに入った後のニーズは異なります。別のユーザーがトランザクション要求を開始すると、この小さな列も赤色のライトが点滅し、「新規取引!」と叫びました。 "、これは、クライアントがメッセージを受信するためにリッスンする必要があることを意味しますよね?つまり、クライアントはページに入るたびに接続を開始します。それ以外の場合は、メッセージをリッスンしてサーバー ポートに接続できます。このサーバーは、それを行うことができます。フロントエンドがメッセージを受信したら、ポップアップ ボックスをクリックしてメインのリアルタイム ビジネスのサーバーに接続します。これにより、サーバー アーキテクチャが複雑になりますが、負荷が増加します。損失は​​改善されると推定されています。私はこの小さなトリックしか理解していません。当面は、少数のユーザーにより良いエクスペリエンスを提供するためだけに、より多くの分散型を検討することはできません


5. 監視の問題: プログラムのロジックは必ずしも完璧ではないため、エラーが発生したり、例外がスローされたりする可能性があり、PHP スクリプトのプロセスが失われ、他の新しいクライアント接続が失敗することがあります。ハングしたかどうかを監視する継続的な監視を行いたいですか?ハングした場合は、exec('phpserver.php')? これは、作業以来の知識によると、デーモンプロセスで実行する必要があります。 PHP では、exec を使用してサーバー スレッドを呼び出しますが、デーモンはどのようにして、前のスレッドがハングアップしたかどうかを特定のディレクトリに自動的に生成するのでしょうか?他のソフトウェアも独自のディレクトリに生成されるように指定できるようです。もしかしたら、独自の file_put_contents によってプロセス番号を決定できるかもしれません


上記の問題についてご意見をいただければ幸いです。ありがとうございます。

ディスカッションへの返信(解決策)

PHPにはWebSocketサーバー機能が用意されていないため、自分で書く場合はループ待機しか使えません。当然、アイドリングもリソースを消費します

サーバーが Linux システムの場合は、PHP とシステム機能を組み合わせた WebSocket サーバーをインターネット上で見つけることができます。オープンソースなので、パフォーマンスも悪くないといわれています

サーバーがWindowsの場合は、純粋なPHPコードを使用しないほうが良いです。そうしないと、将来的にPHPレベルでは解決できない多くのトラブルに遭遇することになります

したがって、本当に自分で書きたい場合は、WebSocket サーバーに関しては、node.js を使用することをお勧めします。少なくとも別の言語を学ぶ必要はありません
Node.js を使用して WebSocket サーバーを作成し、基本的な機能を実装するのに必要なコードは 4 ~ 5 行だけです

その他の問題は基本的にすべて検討済みです。実際の戦闘で 1 つずつ解決しましょう

200 万人以下のユーザーに無料のサードパーティ IM を見ました。 、長い接続を使用します。

これを行うには PHP ソケットを使用します。PHP に完全に依存するのは現実的ではないかもしれません。システム スクリプトを使用する必要があります。 。 。

私もよく調べてないです。 。 。

これを直接使用でき、パフォーマンスは非常に強力です。PC クアッドコアのロングリンク QPS は 15W/S で、単一サーバーで数万のクライアントを簡単にサポートできます。

ホームページ: http://www.workerman. net/ には、ゲームを含む多くの WebSocket の例があります

ソースコード: https://github.com/walkor/workerman

質問に対する答えは次のとおりです:

1 ノンブロッキング + IO 多重化です(Epoll)、サーバーモデルはnginxに似ており、パフォーマンスは非常に優れています
2 プロセス制御が付属しており、php your_file.php start -dは自動的にデーモンモードに入り、php your_file.php stopが停止し、php your_file.phpステータスをチェックします。ステータス
3 変数またはリソースの永続的な保持をサポートします。変数はメモリに配置されます。もちろん、mysql redis などのストレージに配置することもできます
4 元の Web システムおよびその GatewayWorker モデルと独立してデプロイ可能です当然、分散展開をサポートします
5 子プロセスがハングアップした場合は、自動的にプルアップすることができ、ドロップされたステータスを数回確認することで、プロセスがハングアップしたかダウンしたかを確認できます。また、各ビジネス インターフェイスの成功率、呼び出し曲線、時間消費などを監視できる統計監視アプリケーションもあります。

WebSocket サーバーのデモを添付します:

<?phpuse Workerman\Worker;require_once './Workerman/Autoloader.php';// Create a Websocket server$ws_worker = new Worker("websocket://0.0.0.0:2346");// 4 processes$ws_worker->count = 4;// Emitted when new connection come$ws_worker->onConnect = function($connection){    // Emitted when websocket handshake done    $connection->onWebSocketConnect = function($connection)    {        echo "New connection\n";    };};// Emitted when data received$ws_worker->onMessage = function($connection, $data){    // Send hello $data    $connection->send('hello ' . $data);};// Emitted when connection closed$ws_worker->onClose = function($connection){    echo "Connection closed\n";};// Run workerWorker::runAll();



GO を変更してプレイ....

swoole または workerman の場合は、ソースコードを学習せずにそのまま使用してください。 swoole または workman をお勧めします

これを直接使用でき、パフォーマンスは非常に強力で、PC クアッドコアのロングリンク QPS は 15W/S で、単一サーバーで数万のクライアントを簡単にサポートできます

ホームページ: http:/ /www.workerman.net/、上記 ゲームを含む多くの WebSocket の例があります

ソース コード: https://github.com/walkor/workerman

あなたの質問に対する答えは次のとおりです:

1 それは非ですブロッキング + IO 多重化 (Epoll)、サーバー モデルは nginx に似ており、パフォーマンスは非常に優れています
2 プロセス制御が付属しています。php your_file.php start -d は自動的にデーモン モードに入ります。php your_file.php stop は停止します。 .php status はステータスをチェックします
3 変数またはリソースの永続的な保持をサポートし、変数はメモリに配置されます。もちろん、mysql redis などのストレージに配置することもできます
4 元の Web システムから独立してデプロイでき、その GatewayWorker モデルは当然分散展開をサポートします
5 子プロセスがハングアップした場合、自動的に開始でき、プロセスはハングアップしたかどうか、およびハングアップした回数のステータスを通じて確認できます。また、各ビジネス インターフェイスの成功率、呼び出し曲線、時間消費などを監視できる統計監視アプリケーションもあります。

WebSocket サーバーのデモを添付します:

<?phpuse Workerman\Worker;require_once './Workerman/Autoloader.php';// Create a Websocket server$ws_worker = new Worker("websocket://0.0.0.0:2346");// 4 processes$ws_worker->count = 4;// Emitted when new connection come$ws_worker->onConnect = function($connection){    // Emitted when websocket handshake done    $connection->onWebSocketConnect = function($connection)    {        echo "New connection\n";    };};// Emitted when data received$ws_worker->onMessage = function($connection, $data){    // Send hello $data    $connection->send('hello ' . $data);};// Emitted when connection closed$ws_worker->onClose = function($connection){    echo "Connection closed\n";};// Run workerWorker::runAll();


良さそうです、試してみます、ありがとうあなた

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。