【问题标题】:Chunked Encoding Implementation in .NET (or at least pseudo code).NET 中的分块编码实现(或至少是伪代码)
【发布时间】:2010-09-24 00:38:22
【问题描述】:
我为 HTTP/HTTPS 请求编写了一个原始 TCP 客户端,但是我遇到了分块编码响应的问题。 HTTP/1.1 是必需的,因此我应该支持它。
原始 TCP 是我需要保留的业务需求,因此我无法切换到 .NET HTTPWebRequest/HTTPWebResponse 但是,如果有办法将原始 HTTP 请求/响应转换为 HTTPWebRequest/ HTTPWebResponse 可以工作。
【问题讨论】:
标签:
.net
http
encoding
tcp
chunked-encoding
【解决方案1】:
为了将来的参考,我还发现了这个:
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding
【解决方案2】:
最好的起点是http 1.1 specification,它展示了分块的工作原理。特别是第 3.6.1 节。
3.6.1 分块传输编码
分块编码修改了
为了
将其作为一系列块传输,
每个都有自己的尺寸指示器,
随后是一个可选的拖车
包含实体头字段。这
允许动态生成的内容
随
一起转让
所需的信息
收件人验证它有
收到完整的消息。
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
块大小字段是一个字符串
表示大小的十六进制数字
块。分块编码是
以任何大小为
的块结束
零,然后是预告片,其中
以空行结束。
预告片允许发件人
包含额外的 HTTP 标头
消息末尾的字段。这
尾标头字段可用于
指示哪些头字段是
包含在预告片中(参见部分
14.40)。
假设您已经从响应中读取了标头并指向流中的下一个字节,您的伪代码将如下所示:
done = false;
uint8 bytes[];
while (!done)
{
chunksizeString = readuntilCRLF(); // read in the chunksize as a string
chunksizeString.strip(); // strip off the CRLF
chunksize = chunksizeString.convertHexString2Int(); // convert the hex string to an integer.
bytes.append(readXBytes(chunksize)); // read in the x bytes and append them to your buffer.
readCRLF(); // read the trailing CRLF and throw it away.
if (chunksize == 0)
done = true; //
}
// now read the trailer if any
// trailer is optional, so it may be just the empty string
trailer = readuntilCRLF()
trailer = trailer.strip()
if (trailer != "")
readCRLF(); // read out the last CRLF and we are done.
这是忽略块扩展部分,但因为它是用“;”分隔的应该很容易将其拆分出来。这应该足以让你开始。请记住,块大小字符串没有有前导“0x”。