ホームページ > バックエンド開発 > PHPチュートリアル > チャンクエンコーディングの問題

チャンクエンコーディングの問題

WBOY
リリース: 2016-06-23 13:43:08
オリジナル
1130 人が閲覧しました

PHP によって収集されたデータは、チャンク転送エンコーディングです。gzip 圧縮形式でのチャンク エンコーディングの考え方は、次のとおりです。各ブロックはヘッダーとボディ フィールドに分割されます。本文情報は 16 進数のシステム表現であり、ヘッダーと本文は復帰文字と改行文字で区切られ、最後のブロックはブロックが切れていることを示す単一行の 0 で終わります。 。

応答ヘッダー情報:

Array(    [0] => HTTP/1.1 200 OK    [1] => Server: Dict/34002    [2] => Date: Wed, 17 Dec 2014 06:49:22 GMT    [3] => Content-Type: text/html; charset=utf-8    [4] => Transfer-Encoding: chunked    [5] => Connection: keep-alive    [6] => Keep-Alive: timeout=60    [7] => Cache-Control: private    [8] => Last-Modified: Wed, 17 Dec 2014 04:57:49 GMT    [9] => Expires: Wed, 17 Dec 2014 06:49:22 GMT    [10] => Set-Cookie: uvid=VJEncoTSVYJC; expires=Thu, 31-Dec-37 23:55:55 GMT; domain=.dict.cn; path=/    [11] => Content-Encoding: gzip)
ログイン後にコピー


if($this->response_num==200)        {			if($this->is_chunked)			{				//读取chunk头部信息,获取chunk主体信息的长度				$chunk_size = (int)hexdec(fgets($this->conn));				//				while(!feof($this->conn) && $chunk_size > 0) 				{ 					//读取chunk头部指定长度的信息					$this->response_body .= fread( $this->conn, $chunk_size ); 					fseek($this->conn, 2, SEEK_CUR);					$chunk_size = (int)hexdec(fgets( $this->conn,4096)); 			   } 			}			else			{				$len=0;				//读取请求返回的主体信息				while($items = fread($this->conn, $this->response_body_length))				{					$len = $len+strlen($items);					$this->response_body = $items;										//当读取完请求的主体信息后跳出循环,不这样做,貌似会被阻塞!!!					if($len >= $this->response_body_length)					{						break;					}				}			}			            if($this->is_gzip)            {                $this->response_body = gzinflate(substr($this->response_body,10));            }						$this->getTrans($this->response_body);        }
ログイン後にコピー


基本的に、このプロンプトは毎回表示されます:
警告: gzinflate(): E:CodeEditphphttpdict.php の 384 行目のデータ エラー
正常に解析できる場合もありますが、正常に解析できる場合もあります。デコードに問題があります。いくつかの情報を確認し、集中デコード方法を変更しましたが、まだ不十分です


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

デコードには gzdecode を使用できます。 gzdecode を使用してデコードできます

奇妙なことに、次のような結果が得られることがあります:

int (挨拶) こんにちは; こんにちは

警告: gzinflate(): data のようなエラーが表示されることがあります。 E:CodeEditphphttpdict.php の 380 行目でエラーが発生しました

この部分のチャンク デコードでエラーが引き続き表示されると推定されます。ここでの問題は、返されたデータが最初に gzip で圧縮され、次にチャンク化されたチャンクで送信されるため、デコードがプロセスは逆になります


gzdecode を使用してデコードできます

if($this->is_chunked)			{				/* //读取chunk头部信息,获取chunk主体信息的长度				$chunk_size = (int)hexdec(trim(fgets($this->conn)));								while(!feof($this->conn) && $chunk_size > 0) 				{ 					//读取chunk头部指定长度的信息					$this->response_body .= fread( $this->conn, $chunk_size ); 					fseek($this->conn, 2, SEEK_CUR);					$next_line = trim(fgets($this->conn));					if($next_line === '0')					{						echo $next_line;exit();					}					else					{						$chunk_size = (int)hexdec($next_line);					}								   } */					while(!feof($this->conn))					{						$this->response_body .= fread($this->conn, 1024);					}					if(preg_match_all("#\r\n#i", $this->response_body, $match))					{						$result=preg_split("#\r\n#i", $this->response_body, -1, PREG_SPLIT_NO_EMPTY );						// echo "<pre class="brush:php;toolbar:false">";						// print_r($result); 						/* foreach($result as $v)						{							echo $v."<br /><hr />";						}						echo "<hr />"; */					/* 	echo hexdec($result[0])."<br />";						echo mb_strlen($result[1])+mb_strlen($result[2])."<br />"; */												$len = count($result);						$this->response_body='';						for($i=1; $i<$len-1; $i++)						{							$this->response_body .= $result[$i];						}						//echo strlen($this->response_body); exit();					}					else					{						die("匹配结束符失败");					}			}
ログイン後にコピー

基本的な考え方は、まず、ヘッダーを connection:close に変更して、while(!feof($this) を通じてすべてのデータを一度に読み取ることができるようにすることです。 ->conn))

次に、チャンク送信ヘッダーとボディは改行で区切られているため、通常の分割を直接使用して、データ長とデータを含む配列を取得します。最初の項目は、すべてのデータの合計長を表します。 (各チャンクの長さではなく)、これはチャンクのエンコーディングとは少し異なるようです。チャンクに応じたエンコーディングが失敗するのも不思議ではありません。)、配列の最後の項目は終了を示す 0 です。 。 。繰り返しテストしました、OK
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート