本文主要是以HTTP使用\r\n来换行,联想到不同操作系统的换行问题,对HTTP是一种基于文本的协议做了一次有意思的分析。
使用巴克斯范式来表示HTTP消息如下
http-message = start-line
*(message-headerCRLF)
CRLF
[message-header]
从巴克斯范式表示的http消息可以看出,http使用了CRLF作为换行的标志,在实际的抓包过程中,我们也可以看到如下图所示的情况,即\r\n
还记得三大操作系统的换行符吗。Windows系统采用CRLF表示下一行;Linux/UNIX系统采用LF表示下一行;MAC系统采用CR表示下一行(PS;据说MAC OS 现在都换成LF了,求苹果大神确认一下)。我们知道windows和Linux之间互传未经过转换的文件,是会出现问题的。这一现象可以通过cat –A filename进行查看,Linux文件是以$也就是\n结尾的(这就是我们敲命令的时候会跟个$的原因),而将Windows文件拷贝到Linux,会出现^M$结尾,也就是\r\n。有的时候我们可能并不会注意到,因为有的软件会自动将我们的文件做了转换。当然Linux到Windows就有可能出现没有换行的情况啦。
这次我们想关注的是既然HTTP使用\r\n,那么至于不同的操作系统会出现什么样的影响呢?
提到这里,就不得不说一下二进制传输和ASCII传输。这个概念我是在ftp协议里面遇到的。二进制传输很简单,即按二进制的码流进行传输,不论在哪里,内容都是一样的,经常会遇到使用二进制传输文本文件的异常情况。FTP协议中的ASCII传输有如下说明:The sender converts the datafrom an internal character representation to the standard 8-bit NVT-ASCII representation (see the Telnetspecification). The receiver willconvert the data from the standard form to his own internal form.In accordancewith the NVT standard, the <CRLF> sequence shouldbe used where necessary to denote the end of a line of text. (See the discussion of file structure at theend of the Section on Data Representation and Storage.),即FTP使用NVT-ASCII中间格式来解决不同系统之间的异构性(一般的做法是,传输文本考虑使用ASCII传输,而其他诸如视屏等使用二进制),即Linux 的\n传输到windows之后会被转换成\r\n,其实中间的时候已经被转换成为\r\n,因为NVT-ASCII使用的是CRLF。
其实这里面有一点是需要明确一下的,数据在网线上进行传输,最终的形态都是二进制即高低电平的形式在物理层上面传输,我们所要讨论的问题在于其在应用层面做了什么操作。比如FTP,先做转换,完事之后传输。
说完FTP,回来看HTTP是如何传输的。这其实要分成两部分,第一部分是HTTP的头部是如何传输的;第二部分是HTTP的消息实体是如何传输的。就像前面所涉及到的FTP,说的是数据部分要做转换。对于HTTP的消息实体,其传输方式多种多样,可以从头域Content-Encoding中看出来。也就是说消息实体会先经过Content-Encoding编码转换成为中间格式,在到达目的端然后在解码出来,即转换为目的端的情况。这里其实和FTP会经历中间格式是一回事,也就是说对于消息实体换行的事情,中间格式给解决了。这些也就是浏览器的开发者需要考虑实现的。
那么对于HTTP头域是使用了什么编码方式的呢?我们知道数据部分使用具体的编码方式是因为数据部分各种各样,有mp4,xml,txt等多种数据格式,而至于HTTP的头部域,其实就是文本格式,这也是我们经常说HTTP协议是基于文本的协议的原因吧。那么对于文本,我们通常想到的传输方式就是ASCII,即和FTP传输文本采用的NVT-ASCII是一类的事情(这个地方没有在RFC中找到确切的说明,哪位大神找到后告诉我),那么自此,不同系统之间换行空格的事情也就解决了。
其实再仔细的想一想HTTP协议之所以成为基于文本的协议,这也是某种原因吧。因为其和下层的TCP协议还是有着本质上的差别的。
说完了这么多,其实各种编程语言是用\n换行,并没有在windows上面反映出来,其背后的原因也是可以在深入探讨一下的。