原 HTTP协议之Transfer-Encoding
发表于:2018-09-07 18:26:05,已有2233次阅读
说明
HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Fri, 07 Sep 2018 10:17:06 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Connection: close
Transfer-Encoding: chunked
说明是分块传输编码。
分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。
格式
图片来源:https://my.oschina.net/ososchina/blog/666761
伪代码
length := 0 // 用来记录解码后的数据体长度
read chunk-size, chunk-extension (if any) and CRLF // 第一次读取块大小
while (chunk-size > 0) { // 一直循环,直到读取的块大小为0
read chunk-data and CRLF // 读取块数据体,以回车结束
append chunk-data to entity-body // 添加块数据体到解码后实体数据
length := length + chunk-size // 更新解码后的实体长度
read chunk-size and CRLF // 读取新的块大小
}
read entity-header // 以下代码读取全部的头标记,chunked算法只看上面
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length // 头标记中添加内容长度
Remove "chunked" from Transfer-Encoding // 头标记中移除Transfer-Encoding
直接PHP翻译
使用的两个方法:string substr ( string $string , int $start [, int $length ] )
: 截取字符串int stripos ( string $haystack , mixed $needle [, int $offset = 0 ] )
: 查找子串位置
function unchunk($chunked) {
$pos = 0;
$unchunk = '';
$CRLF = "\r\n";
$length = 0; // 用来记录解码后的数据体长度
// 第一次读取块大小:read chunk-size, chunk-extension (if any) and CRLF
echo $chunked.PHP_EOL;
$pos = stripos($chunked, $CRLF);
echo ">>" . $pos . PHP_EOL;
$chunk_size = hexdec(substr($chunked, 0, $pos)); // 十六进制传十进制
echo "HEX: " . substr($chunked, 0, $pos) . " DEC: " . $chunk_size . PHP_EOL;
while($chunk_size > 0) { // 一直循环,直到读取的块大小为0
$pos = $pos + strlen($CRLF); // 跳过CRLF分隔符
$unchunk .= substr($chunked, $pos, $chunk_size); // 读取块数据体,以回车结束
$length = $length + $chunk_size; // 更新解码后的实体长度
$pos = $pos + $chunk_size + strlen($CRLF); // 读取新的块大小, 跳过CRLF分隔符
$idx = stripos($chunked, $CRLF, $pos);
echo ">>" . $idx . PHP_EOL;
$chunk_size = hexdec(substr($chunked, $pos, $idx - $pos));
echo "HEX: " . substr($chunked, $pos, $idx - $pos) . " DEC: " . $chunk_size . PHP_EOL;
$pos = $idx;
}
return $unchunk;
}
最后:优化
function unchunkClear($chunked) {
$idx = 0; // start
$pos = 0; // end
$unchunk = '';
$CRLF = "\r\n";
$CRLFLEN = 2;
$pos = stripos($chunked, $CRLF, $idx);
$chunk_size = hexdec(substr($chunked, $idx, $pos - $idx));
while($chunk_size > 0) {
$idx = $pos + $CRLFLEN;
$unchunk .= substr($chunked, $idx, $chunk_size);
$idx = $idx + $chunk_size + $CRLFLEN;
$pos = stripos($chunked, $CRLF, $idx);
$chunk_size = hexdec(substr($chunked, $idx, $pos - $idx));
}
return $unchunk;
}
暂无评论