2016-12-25 1 views
1

私は小さなWebSocketライブラリを書いていましたが、gzipサポートの追加は驚くほど簡単でした。 deflate_init()//inflate_init()/inflate_add()の関数が実際にはPHP 7のみであったため、PHP 5環境でWebSocketサーバーを実行したいと考えていました。gzdecode()とinflate_add()との間のバイナリの相互運用性

私の問題は、deflate_add()は、gzdeflate()と少し異なる出力を生成します。これは以下のテストケースの1文字です。

deflate_add()/inflate_add()ベースのアプローチをして、ブラウザ完璧に動作し、のでgzdeflate()の出力が不正です。私はgzdeflate()/gzinflate()は、さまざまな基本的なオプションを持つzlibを使用していると推測しています - 何かストリームの状態に関連する、多分?それはすべてが崩壊する原因となっています。

最終的に私は、PHP 5のzlib関数が "正しい"収縮したデータを出力することを納得できるかどうかを知りたいと思います。すべての


まず、私はPHP 7で使用deflate_init()/deflate_add()ベースのアプローチ:

$data = "ABC"; 

$ctx = deflate_init(ZLIB_ENCODING_RAW); 

// unfortunately I can't find the gigantic blog post with example code 
// that I learned from :(, but it contained the Ruby equivalent of the 
// the substr() below. I blinked at it a bit but apparently this is how 
// it's done. 
$deflated = substr(deflate_add($ctx, $data, ZLIB_SYNC_FLUSH), 0, -4); 

// $deflated is now "rtr\6\0" 

$ictx = inflate_init(ZLIB_ENCODING_RAW); 

$data2 = inflate_add($ictx, $deflated, ZLIB_NO_FLUSH); 

// $data2 is now "ABC" 

ここで私はgzdeflate()/gzinflate()を使用した場合に何が起こるかです:

しようとして
$data = "ABC"; 

$deflated = gzdeflate($data, 9, ZLIB_ENCODING_RAW); 

// $deflated is now "str\6\0" 

$output = gzinflate($deflated); 

// $output is now "ABC" 

gzinflate()inflate_add()の出力はdata error。 TL:DR:

print gzinflate("rtr\6\0")."\n"; // will bomb out 

print gzinflate("str\6\0")."\n"; // prints "ABC" 

答えて

0

あなたは正しいと言っているものが正しくありませんし、正しくないものが正しいと思います。

deflate_addを使用すると、意図せずに終了していない無効なストリームを作成しています。なぜ、私は分かりません。 (これはあなたが見つけることができない "巨大なブログの投稿"から来たので、明らかに、あなたはしません)。これは、現在のdeflateブロックを完成し、空の格納されたブロックを追加するZLIB_SYNC_FLUSHで行われています。 substr(,,-4)は、最後に空の格納ブロックの大半を削除しています。不完全で無効なinflateストリームが残っています。格納されているブロックの途中で途中で終了します。一方、最後のブロックとしてマークされた単一の収縮ブロックを有する、適切に終結された収縮ストリームを生成することである。 2つのストリームの唯一の違いは、最初の(最下位)ビットで、最後のブロックをマークする1です。

あなたは、適切に終了したデフレートストリームが「すべてが崩壊する」とは言いません。いずれにしても、ではなくZLIB_FINISHの代わりにsubstrを使用して、適切に終了するデフレートストリームをdeflate_addにすることができます。

gzdeflateで無効なデフレートストリームを作成する方法はありません。大きな文字列の場合、最後のブロックが最初のブロックではない可能性があるため、最初のビットを変更するだけではなりません。