http://hi.baidu.com/aaxh/blog/item/0c6239f3d8592152342acc20.html
章: PHP とソケット タイトル: "PHP Game Programming" 著者: Matt Rutledget 翻訳: heiyeluren ◇ ソケットの基本 ◇ サーバーを生成する ◇ クライアントを生成する この章では、魅力的でわかりにくいソケットについて学びましょう。ソケットは、PHP ではあまり活用されていない機能です。今日は、クライアント接続を使用できるサーバーを生成し、クライアント上のソケットを使用して接続する方法を説明します。サーバーは詳細な処理情報をクライアントに送信します。 完全なソケット プロセスが表示されたら、それを将来のプログラム開発に使用します。サーバーは接続を可能にする HTTP サーバーであり、クライアントは Web ブラウザーです。これは単一のクライアント/サーバーの関係です。 ◆ ソケットの基本 PHP は、Berkley のソケット ライブラリを使用して接続を作成します。ソケットは単なるデータ構造であることがわかります。このソケット データ構造を使用して、クライアントとサーバー間のセッションを開始します。このサーバーは常にリッスンし、新しいセッションを生成する準備をしています。クライアントがサーバーに接続すると、サーバーがセッションを待機しているポートが開きます。このとき、サーバーはクライアントの接続要求を受け入れ、サイクルを実行します。これで、クライアントはサーバーに情報を送信できるようになり、サーバーもクライアントに情報を送信できるようになります。 ソケットを生成するには、プロトコル、ソケット タイプ、パブリック プロトコル タイプの 3 つの変数が必要です。ソケットを生成するときに選択できるプロトコルは 3 つあります。詳細なプロトコルの内容については、以下を読み続けてください。 パブリック プロトコル タイプの定義は、接続に不可欠な要素です。以下の表では、一般的なプロトコルの種類を示します。 表 1: プロトコル 名前/定数の説明 AF_INET これは、送信に TCP または UDP を使用し、ソケットの生成に使用され、IPv4 アドレスに使用されるほとんどのプロトコルです AF_INET6 上記と似ていますが、IPv6 アドレスに使用されます AF_UNIX Unix および Linux システムで使用されるローカル プロトコル。通常、クライアントとサーバーが同じマシン上にある場合に使用されます。 SOCK_STREAM このプロトコルは、シーケンシャルです。信頼性の高い、データ統合されたバイト ストリーム ベースの接続。これは最も一般的に使用されるソケットのタイプです。このソケットは送信に TCP を使用します。 SOCK_DGRAM このプロトコルは、コネクションレス型の固定長転送呼び出しです。このプロトコルは信頼性が低く、接続に UDP を使用します。 SOCK_SEQPACKET このプロトコルは、固定長のデータ パケットを送信して送信するデュアルラインの信頼性の高い接続です。このパッケージを読み取る前に、完全に受け入れる必要があります。 SOCK_RAW このソケット タイプは、ICMP パブリック プロトコルを使用して単一のネットワーク アクセスを提供します。 (ping とtraceroute はこのプロトコルを使用します) SOCK_RDM このタイプはめったに使用されず、ほとんどのオペレーティング システムでは実装されていません 表 3: パブリック プロトコル 名前/定数の説明 ICMP インターネット制御メッセージ プロトコル、主にゲートウェイとホストでネットワークの状態を確認し、エラー メッセージを報告するために使用されます UDP ユーザー データ メッセージ プロトコル、コネクションレスで信頼性の低い伝送プロトコル TCP 伝送制御プロトコル、最も一般的信頼性の高いパブリック プロトコルを使用しているため、送信プロセス中にエラーが発生した場合は、データ パケットが受信者に確実に到達します。エラー パケットが再送信されます。 ソケットを生成するための 3 つの要素がわかったので、PHP のsocket_create() 関数を使用してソケットを生成します。 socket_create() 関数には、プロトコル、ソケット タイプ、パブリック プロトコルの 3 つのパラメータが必要です。 ocket_create() 関数は、正常に実行された場合はソケットを含むリソース タイプを返し、失敗した場合は false を返します。 Resourcesocket_create(int protocol, intソケットType, int commonProtocol); ソケットを生成したら、その後はどうなるでしょうか? PHP には、ソケットを操作するための関数がいくつか用意されています。ソケットを IP にバインドし、ソケットの通信をリッスンし、ソケットを受け入れることができます。次に、関数がソケットを生成、受け入れ、リッスンする方法を理解するための例を見てみましょう。 $commonProtocol = getprotobyname("tcp"); $socket =ソケット_create(AF_INET, SOCK_STREAM, $commonProtocol); ソケット_リッスン($socket); ; // ソケット機能をさらに追加予定 ?> 上記の例では、独自のサーバーを生成します。例の最初の行、 $commonProtocol = getprotobyname(“tcp”); パブリック プロトコル名を使用してプロトコル タイプを取得します。ここでは TCP パブリック プロトコルが使用されます。UDP または ICMP プロトコルを使用する場合は、getprotobyname() 関数のパラメータを「udp」または「icmp」に変更する必要があります。別の方法は、getprotobyname() 関数を使用せず、socket_create() 関数で SOL_TCP または SOL_UDP を指定することです。 $socket =ソケット_create(AF_INET, SOCK_STREAM, SOL_TCP); 例の 2 行目はソケットを生成し、ソケット リソースのインスタンスを返します。ソケット リソースのインスタンスを取得したら、ソケットを IP アドレスとポートにバインドする必要があります。 socket_bind($socket, ‘localhost’, 1337); ここでは、ソケットをローカル コンピューター (127.0.0.1) にバインドし、ソケットを 1337 ポートにバインドします。次に、すべての受信ソケット接続をリッスンする必要があります。 socket_listen($socket); 4 行目以降は、すべてのソケット関数とその使用法を理解する必要があります。 表 4: ソケット関数 関数名 説明 ソケット_accept() ソケット接続を受け入れます ソケット_bind() ソケットをIPアドレスとポートにバインドします ソケットクリア_エラー() ソケットエラーまたは最後のエラーコードをクリアします ソケット_クローズ( ) 閉じるソケットリソース socket_connect() ソケット接続を開始します socket_create_listen() 指定されたポートでリッスンするソケットを開きます socket_create_pair() 未分化ソケットのペアを配列に生成します socket_create() ソケットを生成します。ソケット ソケットのデータ構造 ソケット_get_option() ソケット オプションを取得します ソケット_getpeername() リモートの同様のホストの IP アドレスを取得します ソケット_getsockname() ローカル ソケットの IP アドレスを取得します ソケット_iovec_add() 新しいベクトルを分散/集約配列 socket_iovec_alloc() この関数は、送信、受信、読み取り、書き込みができる iovec データ構造を作成します socket_iovec_delete() は、割り当てられた iovec を削除します socket_iovec_fetch() は、指定された iovec リソースのデータを返します socket_iovec_free() は、 iovec リソース socket_iovec_set() 設定 iovec の新しいデータ値 socket_last_error() 現在のソケットの最後のエラー コードを取得する socket_listen() 指定されたソケットからのすべての接続をリッスンする socket_read() 指定された長さのデータを読み取る socket_readv() スキャッター/集約配列からデータを読み取ります ソケット_recv() ソケットからキャッシュへのデータを終了します ソケット_recvfrom() 指定されたソケットからデータを受け取ります。指定されていない場合、現在のソケットがデフォルトになります ソケット_recvmsg() iovec からメッセージを受信します socket_select() 複数選択 socket_send() この関数は、接続されているソケットにデータを送信します socket_sendmsg() はソケットにメッセージを送信します socket_sendto() は指定されたアドレスのソケットにメッセージを送信します socket_set_block() はソケットを次のように設定しますブロックモード socket_set_nonblock() ソケットを非ブロックモードに設定します socket_set_option() ソケットオプションを設定します socket_shutdown() この関数により、読み取り、書き込み、または指定されたソケットを閉じることができます socket_strerror() 指定された内容の詳細なエラーを返しますエラー番号 socket_write() ソケットキャッシュにデータを書き込む socket_writev() 分散/集約配列にデータを書き込む (注:関数紹介は原文の一部を削除しています。英語の原文を参照することをお勧めします)関数の詳細な使用方法については、PHP マニュアルを参照してください) 上記の関数はすべて PHP のソケットに関するものです。これらの関数を使用するには、ソケットを開く必要があります。開いていない場合は、php.ini を編集してください。ファイルを開き、次の行の前にあるコメントを削除します: extension=php_sockets.dll コメントを削除できない場合は、次のコードを使用して拡張ライブラリをロードしてください: if(!extension_loaded('ソケット')) { if(strtoupper(substr(PHP_OS, 3)) == "WIN") { dl('php_sockets.dll ') } else { dl('sockets.so' ); } } ?> ソケットが開いているかどうかがわからない場合は、phpinfo() 関数を使用してソケットを開くかどうかを判断できます。ソケットが開いているかどうかは、phpinfo 情報を確認することで確認できます。以下に示すように: ソケットに関する phpinfo() 情報を表示 ◆ サーバーを生成 🎜次に、最初の例を改良してみましょう。特定のソケットをリッスンし、ユーザー接続を処理する必要があります。 $commonProtocol = getprotobyname("tcp"); $socket =ソケット_create(AF_INET, SOCK_STREAM, $commonProtocol); ソケット_リッスン($socket); ; // サーバーへの受信接続を受け入れます $connection =ソケット_accept($socket); if($connection) { ソケット_write($connection, "ソケットに接続しました...nr");この例を実行するには、コマンド プロンプトを使用する必要があります。その理由は、ここでは Web ページではなくサーバーが生成されるためです。 Web ブラウザを使用してこのスクリプトを実行しようとすると、30 秒の制限を超える可能性が高くなります。以下のコードを使用して無限の実行時間を設定できますが、コマンド プロンプトを使用して実行することをお勧めします。 set_time_limit(0); コマンド プロンプトでこのスクリプトをテストしてください: Php.exe example01_server.php システムの環境変数に php インタープリターへのパスを設定していない場合は、php.exe を指定する必要があります。詳細なパスを指定します。サーバーを実行するときは、Telnet 経由でポート 1337 に接続してサーバーをテストできます。以下に示すように: 上記のサーバーには 3 つの問題があります: 1. 複数の接続を受け入れることができません。 2. 1 つのコマンドのみを完了します。 3. Web ブラウザからこのサーバーに接続することはできません。 この最初の問題は解決するのが簡単です。アプリケーションを使用して毎回サーバーに接続できます。しかし、次の問題は、Web ページを使用してサーバーに接続する必要があることですが、これはさらに困難です。サーバーに接続を受け入れさせ、クライアントにデータを書き込み (書き込む必要がある場合)、接続を閉じて次の接続を待つことができます。 前のコードを改良し、次のコードを生成して新しいサーバーを作成します。 // ソケットをセットアップします $commonProtocol = getprotobyname("tcp") $socket =ソケット_create(AF_INET, SOCK_STREAM); , $commonProtocol); socket_listen($socket); $buffer = "NO DATA" { //このソケットで受信するすべての接続を受け入れます $connection =ソケット_accept($socket); printf("Socket Connectedrn"); // バッファーに何かがあるかどうかを確認します if( $buffer != "" ) { printf("何かがバッファ内にあります...データを送信しています...rn"); printf("socketrn に書き込みました"); else { printf("No Data in thebufferrn"); } // 入力を取得します while($data =ソケット_read($connection, 1024, PHP_NORMAL_READ)) { $buffer = $data; printf("ソケットを閉じました" ); printf("バッファ: " . $buffer . "rn"); > このサーバーは何をすべきですか?ソケットを初期化し、データを送受信するためにキャッシュを開きます。接続を待機し、接続が確立されると、サーバー側の画面に「ソケットが接続されました」と表示されます。このサーバーはバッファをチェックし、バッファ内にデータがある場合は、接続されているコンピュータにデータを送信します。次に、このデータに対する受け入れメッセージを送信し、メッセージを受け入れると、メッセージをデータに保存し、接続されているコンピュータにメッセージを認識させ、最後に接続を閉じます。接続が閉じられると、サーバーは次の接続の処理を開始します。 (悪い翻訳、原文添付) これがサーバーの動作です。 データの受信と送信に使用するソケットとバッファを初期化し、接続が作成されると を出力します。次に、サーバーは、バッファー内に何かがあるかどうかを確認し、存在する場合は、接続されているコンピューターにデータを送信します。 データを送信した後、情報の受信を待ちます。情報を受信すると、それをデータに保存し、接続されているコンピューターに情報を受信したことを通知し、 接続が閉じられた後、サーバーは プロセス全体を再度開始します ◆ 2 番目の問題を処理するためにクライアント を生成するのは簡単です。 PHP ページを生成し、ソケットに接続し、データをそのキャッシュに送信して処理する必要があります。データを再度処理した後、データをサーバーに送信できます。別のクライアント接続では、そのデータが処理されます。 2 番目の問題を解決するには、 ソケットに接続する PHP ページを作成し、バッファー内のデータを受信して、 バッファー内のデータを処理した後、それを処理する必要があります。別のクライアントがサーバーに接続すると、送信したデータが処理され、クライアントはさらにデータをサーバーに送り返します。 / / ソケットを作成して接続します $socket =ソケット_create(AF_INET, SOCK_STREAM, SOL_TCP); $connection =ソケット_connect($socket,'localhost', 1337) while($buffer =ソケット_read($socket, 1024, PHP_NORMAL_READ) ) ) { if($buffer == “NO DATA”) { echo(“NO DATA ”); Break; } else { // で何かを行うバッファ内のデータ echo(“Buffer Data: “ . $buffer . “ ”); } } echo(“Socket への書き込み ” ) ; // テスト データをソケットに書き込みます if(!socket_write($socket, “SOME DATArn”)) { echo(“書き込みに失敗しました ”) } / / ソケットからの応答を読み取ります while($buffer =ソケット_read($socket, 1024, PHP_NORMAL_READ)) { echo(“送信されたデータは: SOME DATA 応答は:” . $buffer . “ ”); } echo(“Done Reading from Socket ”); このサンプルコードは、サーバーに接続するクライアントを示しています。クライアントはデータを読み取ります。これがこのサイクルで到着する最初の接続である場合、サーバーは「NO DATA」をクライアントに送り返します。これが発生した場合、クライアントは接続の最上位にあります。クライアントはデータをサーバーに送信し、データはサーバーに送信され、クライアントは応答を待ちます。応答を受信すると、応答を画面に書き込みます。
|