php_PHP チュートリアルでの WebSocket の使用例

WBOY
リリース: 2016-07-13 10:36:04
オリジナル
915 人が閲覧しました

この記事では主に PHP での WebSocket の使用例を紹介します。必要な方は参考にしてください。以下に、クライアントとサーバーの間で WebSocket 接続を確立するときのハンドシェイク部分を示す図を描きました。この部分は、ノードによって提供されるネット モジュールがこの時点で既にカプセル化されているため、ノード内で非常に簡単に完了できます。接続の確立を考慮せずに、データの相互作用のみを考慮する必要があります。ただし、PHPはそうではなく、ソケットの接続、確立、バインディング、監視などを自分で操作する必要があるため、取り出して話す必要があります。 ​ php使用websocket示例      帮客之家 ​ ①と②は実際にはHTTPリクエストとレスポンスですが、処理中に取得するのは解析されていない文字列です。のように: ​ コードは以下のように表示されます: GET /チャット HTTP/1.1 ホスト:server.example.com 出典: http://www.jb51.com ​ ​ 私たちが通常目にするリクエストは次のようになります。これがサーバーに到達すると、いくつかのコード ライブラリを通じてこの情報を直接取得できます。 ​ 1.phpでWebSocketを処理する ​ WebSocket 接続はクライアントによってアクティブに開始されるため、すべてはクライアントから開始する必要があります。最初のステップは、クライアントから送信された Sec-WebSocket-Key 文字列を解析することです。 ​ コードは以下のように表示されます: GET /チャット HTTP/1.1 ホスト:server.example.com アップグレード: Webソケット 接続: アップグレード Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== 出典: http://www.jb51.com Sec-WebSocket-Protocol: チャット、スーパーチャット Sec-WebSocket-バージョン: 13 ​ ​ クライアントリクエストフォーマット ​ まず、php はソケット接続を確立し、ポート情報をリッスンします。 ​ 1. ソケット接続の確立 ​ ソケットの確立については、大学でコンピュータ ネットワークを学んだことがある方はご存知かと思いますが、次のような接続の確立プロセスがあります。 ​ php_PHP チュートリアルでの WebSocket の使用例 ​ コードは以下のように表示されます: // ソケットソケットを作成します $master = ソケット_作成(AF_INET, SOCK_STREAM, SOL_TCP); ソケットセットオプション($master, SOL_SOCKET, SO_REUSEADDR, 1); ソケットバインド($マスター、$アドレス、$ポート); ソケット_リッスン($マスター); ​ ​ ここの処理はnodeに比べて非常に面倒です。上記のコードは接続を確立するものではありませんが、ソケットを確立するために書かなければならないコードです。処理プロセスが少し複雑なので、管理や呼び出しを容易にするために、さまざまな処理をクラスに記述しました。​ コードは以下のように表示されます: //デモ.php クラス WS { var $master // クライアントがサーバーに接続します。 var $sockets = array(); // さまざまな状態のソケット管理 var $handshake = false // 握手をするかどうかを決定します。 ​ 関数 __construct($address, $port){ //ソケットソケットを作成する $this->master =socket_create(AF_INET, SOCK_STREAM, SOL_TCP) または die("socket_create() failed"); socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) または die("socket_option() failed"); ソケットバインド($this->マスター, $アドレス, $ポート) または die("socket_bind() failed"); socket_listen($this->master, 2) または die("socket_listen() failed"); ​ $this->sockets[] = $this->master; ​ // デバッグ echo("マスターソケット: ".$this->master."n"); ​ while(true) { // 受信メッセージのソケットを自動的に選択します。ハンドシェイクの場合は、ホストを自動的に選択します。 $write = NULL; $excel = NULL; ソケット_select($this->ソケット, $write, $excel, NULL); ​ foreach ($this->sockets as $socket) { //ホストに接続するクライアント if ($socket == $this->master){ $client =ソケット_accept($this->master); if ($client sockets, $client); echo "Connect Clientn";                                               } それ以外 { $bytes = @socket_recv($socket,$buffer,2048,0);                                                                                                                                                                                                                                                                                                            if (!$this->ハンドシェイク) { // 握手をしない場合は、まず握手をして応答してください //doHandShake($socket, $buffer); エコー「ShakeHandsn」; } それ以外 { に $buffer = decode($buffer); //process($socket, $buffer); エコー「Filenを送信」;                                               } } } } } } ​ ​ ​ 上記のコードは私がデバッグしたもので、大きな問題はありません。テストしたい場合は、cmd コマンド ラインに php /path/to/demo.php と入力できます。もちろん、上記は単なるクラスです。テストしたい場合は、新しいインスタンスを作成する必要があります。​ コードは以下のように表示されます。 $ws = 新しい WS('localhost', 4000); ​ ​ クライアント コードはもう少し単純になります。 ​ コードは以下のように表示されます。 var ws = 新しい WebSocket("ws://localhost:4000"); ws.onopen = function(){ console.log("ハンドシェイクが成功しました"); }; ws.onerror = function(){ console.log("エラー"); }; ​ ​ サーバー コードを実行すると、クライアントが接続すると、以下が表示されます。 ​ php_PHP チュートリアルでの WebSocket の使用例 ​ 2. Sec-WebSocket-Key 情報を抽出する ​ コードは以下のように表示されます。 関数 getKey($req) { $key = null; if (preg_match("/Sec-WebSocket-Key: (.*)rn/", $req, $match)) { $key = $match[1]; } $key を返します。 } ​ ​ ここでは比較的単純です。WebSocket 情報ヘッダーには Sec-WebSocket-Key が含まれている必要があるため、すぐに照合できます。 ​ 3. 暗号化 Sec-WebSocket-Key ​ コードは以下のように表示されます。 関数 encry($req){ $key = $this->getKey($req); $mask = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; ​ returnbase64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)); } ​ ​ ​ SHA-1 で暗号化された文字列は、base64 で暗号化されます。暗号化アルゴリズムが間違っている場合、クライアントは以下のチェック時にエラーを直接報告します。 ​ php_PHP チュートリアルでの WebSocket の使用例 ​ 4. Sec-WebSocket-Accept を返信します ​ コードは以下のように表示されます。 関数 dohandshake($socket, $req){ // 暗号化キーを取得する $acceptKey = $this->encry($req); $upgrade = "HTTP/1.1 101 スイッチング プロトコル" 。 「アップグレード: websocketrn」 。 「接続: アップグレード」 。 "Sec-WebSocket-Accept: " . $acceptKey . " . "rn"; ​ //ソケットへの書き込み socket_write(ソケット,$upgrade.chr(0), strlen($upgrade.chr(0))); // ハンドシェイクが成功したことをマークします。次回データが受け入れられるとき、データはデータ フレーム形式になります。 $this->ハンドシェイク = true; } ​ ​ ​ ここで注意しなければならないのは、すべてのリクエストと対応する形式の最後に空白行があることです。これは、テストを開始したときに失われ、長い間苦労しました。 php_PHP チュートリアルでの WebSocket の使用例 ​ ​ クライアントがキーのチェックに成功すると、onopen 関数がトリガーされます。 php_PHP チュートリアルでの WebSocket の使用例 ​ ​ 5. データフレーム処理 ​ コードは以下のように表示されます。 // データフレームを解析します 関数デコード($buffer) { $len = $masks = $data = $decoded = null; $len = ord($buffer[1]) & 127; ​ if ($len === 126) { $マスク = substr($buffer, 4, 4); $data = substr($buffer, 8); } else if ($len === 127) { $マスク = substr($buffer, 10, 4); $data = substr($buffer, 14); } それ以外 { $マスク = substr($buffer, 2, 4); $data = substr($buffer, 6); } for ($index = 0; $index frame($msg); ソケット書き込み($client, $msg, strlen($msg)); } ​ ​ ​ クライアントコード: ​ ​ コードは以下のように表示されます: var ws = 新しい WebSocket("ws://localhost:4000"); ws.onopen = function(){ console.log("ハンドシェイクが成功しました"); }; ws.onmessage = function(e){ console.log("メッセージ:" + e.data); }; ws.onerror = function(){ console.log("エラー"); }; ws.send("李静"); ​ ​ 接続後にデータを送信すると、サーバーは次のように戻ります。 ​ php_PHP チュートリアルでの WebSocket の使用例 ​ ​ ​ 2. 問題に注意する ​ 1.WebSocketのバージョンの問題 ​ ハンドシェイク中のクライアントのリクエストには、バージョン識別子である Sec-WebSocket-Version: 13 が含まれており、現在のすべてのブラウザはこのバージョンを使用します。以前のバージョンでは、データ暗号化の部分でさらに問題が発生し、次の 2 つのキーが送信されました。 ​ コードは以下のように表示されます: GET /チャット HTTP/1.1 ホスト:server.example.com アップグレード: Webソケット 接続: アップグレード 出典: http://www.jb51.net Sec-WebSocket-Protocol: チャット、スーパーチャット Sec-WebSocket-Key1: xxxx Sec-WebSocket-Key2: xxxx ​ ​ このバージョン(古いため使用されなくなったバージョン)の場合は、次の方法で入手する必要があります ​ ​ コードは以下のように表示されます: function encry($key1,$key2,$l8b){ //数値を取得します preg_match_all('/([d]+)/', $key1, $key1_num); 、$key2、$key2_num); ​ $key1_num = 爆破($key1_num[0]); $key2_num = implode($key2_num[0]); //スペースを数える preg_match_all('/([ ]+)/', $key1, $key1_spc); preg_match_all('/([ ]+)/', $key2, $key2_spc); ​ if($key1_spc==0|$key2_spc==0){ $this->log("無効なキー");return; // いくつかの数学 $key1_sec = Pack("N",$key1_num / $key1_spc); $key2_sec = Pack("N",$key2_num / $key2_spc); ​ return md5($key1_sec.$key2_sec.$l8b,1); } ​ ​ ​ この検証方法については文句を言うとキリがないです! nodeJsのWebSocket操作方法と比較すると以下のようになります。 ​ ​ コードは以下のように表示されます: //サーバープログラム var crypto = require('crypto'); var WS = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; require('net').createServer(function(o){ var キー; o.on('データ',function(e){ if(!キー){ //握手をする key = e.toString().match(/Sec-WebSocket-Key: (.+)/)[1]; key = crypto.createHash('sha1').update(key + WS).digest('base64'); o.write('HTTP/1.1 101 スイッチング プロトコル'); o.write('アップグレード: websocketrn'); o.write('接続: アップグレード'); o.write('Sec-WebSocket-Accept: ' + key + 'rn'); o.write('rn'); }それ以外{ コンソール.ログ(e); }; }); }).listen(8000); ​ ​ 2. データフレーム解析コード ​ この記事では、decodeFrame などのデータ フレーム解析コードは提供しません。データ フレームの形式は、純粋に物理的な作業です。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/740820.html技術記事この記事では主に PHP で WebSocket を使用する例を紹介します。必要な方は参考にしてください。これは、クライアントとサーバー間の WebSocket 接続を確立する際のハンドシェイク部分を示すために以下の図を描きました。
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!