用C实现一个html读取程序,其实就是个迷你“浏览器”。
可以读取网页的html。然而遇到了似乎是jsp的站点,不过扩展名被重写为htm。它是用chunked方式分块发送html的
搞了好久才正常解析这种http封包。为了调试,保存成文件,结果问题来了。
每个换行变成了0x0d 0x0d 0x0a,但是http首部和其他地方都正常,我原以为是网站程序员疏忽,程序了多写了个0x0d
比如:sprintf( ... "\r\r\n" ...),后来逐个字节分析,发现完全正常,于是认定是stdio的问题
对比从IE上查看源代码的结果:
每一个chunk是追加到文件末尾的,比如:
pf = fopen("1.txt", "a+");
使用这种方式的时候,windows下会自动把0x0a转为0x0d 0x0a,原来的0x0d 0x0a自然就变成了0x0d 0x0d 0x0a!
解决方法是用二进制来读写:
pf = fopen("1.txt", "ab");
这样就完全正常了,把每一个chunk的数据拼起来,和从IE上查看源文件的结果是一模一样的。
此外,每个chunk的结构也跟大家分享一下,可以参考http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
不过那是全英文的,可能部分网友会蛋痛:
http首部就不说了,会有一个Transfer-Encoding: Chunked而没有Content-Length: xxx段,同样以两个\r\n结束http头部
下面就是每一个chunk的内容,直到最后一个chunk:
chunk 1
chunk 2
...
chunk n
last-chunk
trailer
CRLF
chunk 1到chunk n是16进制文本开头的chunk长度,然后是一个\r\n,接着是内容,再一个\r\n。长度仅仅是内容的长度。
比如2000\r\n*******\r\n 是8192个字节的内容,winsock好像最大一个包裹就是8K。
last-chunk是最后一个chunk,其长度段为"0",就是16进制0。读取到这个,后面的包都可以丢弃了,因为接收是协议来完成的
你不读取,也不会影响正常通信,反正数据已经到达你的计算机了。
当然你可以继续读取,直到\r\n\r\n出现说明http包裹完全结束。