关于C/C++使用stdio读写文件的有关问题

关于C/C++使用stdio读写文件的问题

用C实现一个html读取程序,其实就是个迷你“浏览器”。

可以读取网页的html。然而遇到了似乎是jsp的站点,不过扩展名被重写为htm。它是用chunked方式分块发送html的

搞了好久才正常解析这种http封包。为了调试,保存成文件,结果问题来了。

 

每个换行变成了0x0d 0x0d 0x0a,但是http首部和其他地方都正常,我原以为是网站程序员疏忽,程序了多写了个0x0d

比如:sprintf( ... "\r\r\n" ...),后来逐个字节分析,发现完全正常,于是认定是stdio的问题

关于C/C++使用stdio读写文件的有关问题

对比从IE上查看源代码的结果:

关于C/C++使用stdio读写文件的有关问题

 

每一个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包裹完全结束。