我为HTTP/HTTPS请求编写了一个原始TCP客户端,但是我遇到了分块编码响应的问题.HTTP/1.1是必需的,因此我应该支持它.
原始TCP是我需要保留的业务需求,因此我无法切换到.NET HTTPWebRequest/HTTPWebResponse但是如果有办法将RAW HTTP请求/响应转换为HTTPWebRequest/HTTPWebResponse那就可以了.
最好的起点是http 1.1规范,它规定了分块的工作原理.特别是第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)chunk-size字段是一个十六进制数字字符串,表示
块的大小.分块编码由任何大小
为零的块结束,后跟预告片,后者由空行终止.预告片允许发件人
在邮件末尾包含其他HTTP标头字段.Trailer标题字段可用于指示预告片中包含哪些标题字段(请参阅第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.
这忽略了块扩展部分,但由于它以";"分隔.它应该很容易分开.这应该足以让你入门.请记住,chunksize字符串没有前导"0x".