问题

为什么在 HTTP 协议中,使用的是 Windows 换行方式而不是 UNIX 换行方式?

回答
在 HTTP 协议中,之所以选择使用 Windows 换行方式(CRLF,即回车符 ` ` 后跟换行符 ` `)而不是 UNIX 换行方式(LF,即换行符 ` `)作为协议的分隔符,这背后有着深厚的历史原因和技术考量。要详细理解这一点,我们需要深入探讨以下几个方面:

1. 历史渊源:早期操作系统的文本处理方式

电传打字机(Teletypewriter, TTY)时代: 早期的计算机终端和打印机大多基于电传打字机技术。在这些设备上,回车符(Carriage Return, CR)的作用是将打印头或光标移动到当前行的开头,而换行符(Line Feed, LF)的作用是将打印头或光标移动到下一行。
早期的操作系统和终端:
MAC OS (Classic, 早期版本): 在 Apple 经典的 Mac OS(非 OS X)中,文本文件和终端输出通常只使用 CR (` `) 来表示换行。这被认为是模拟了电传打字机上按下回车键同时完成“归位”和“换行”的概念。
UNIX (以及后来的 Linux, macOS): UNIX 系统以及其衍生系统(如 Linux, macOS)在设计上更加简洁高效,它们决定只使用 LF (` `) 来表示换行。这是因为在许多终端和打印机上,单独的 LF 也能实现换行的功能,而且只需要一个字节,更为高效。
MSDOS / Windows: MSDOS 和后来的 Windows 操作系统,在表示文本换行时,采用了 CRLF (` `) 的组合。这被认为是为了更精确地模拟物理设备的操作,即先将打印头“归位”到行首(CR),然后再“换到下一行”(LF)。

2. HTTP 协议的设计选择:兼容性与历史包袱

HTTP 协议是在互联网早期(主要由 NCSA Mosaic 浏览器和 CERN 的 HTTPd 服务器推动)发展起来的。当时,主要的 Web 服务器和客户端操作系统是多种多样的,其中 Windows(及其前身 MSDOS)占据了相当大的市场份额。

早期 Web 服务器的实现: 早期许多 Web 服务器是由熟悉 MSDOS/Windows 环境的开发者编写的。他们在实现协议时,自然而然地会遵循他们所熟悉的操作系统环境中文本处理的惯例。
网络通信的文本协议: HTTP 本质上是一个文本协议,它依赖于特定的控制字符来分隔消息的不同部分,例如请求行、头部字段、请求体等。这些分隔符需要被客户端和服务器都能够准确地解析。
CRLF 的优越性(在当时被认为如此):
明确的双重动作: CRLF 被认为能够更明确地指示“回到行首然后换到下一行”。这在一些较老的终端或打印机上可能更有优势,因为它们可能需要明确的归位信号。
与早期网络协议的相似性: 许多早期的网络协议,如 FTP、SMTP 等,也广泛使用了 CRLF 作为行分隔符。HTTP 作为一种新兴的传输层协议,采用与现有成熟协议相似的分隔符有助于简化开发和提高互操作性。
避免混淆: 如果 HTTP 使用了像 UNIX 的 LF 这样的单字节换行符,在处理来自 Windows 环境的文件传输(例如上传文本文件)时,可能会出现问题。Windows 文件中的 CRLF 在被当作普通文本内容读取时,可能会被误解为两个独立的控制字符。

3. 技术原因和潜在问题:为什么不是 LF?

Windows 文件系统和应用程序的依赖: Windows 应用程序和文件系统在处理文本文件时,普遍依赖于 CRLF 作为行分隔符。如果 HTTP 协议使用 LF,一些 Windows 上的应用程序在生成或解析 HTTP 消息时,可能会出现意想不到的行为,例如:
在发送包含文本数据的请求体(如 POST 请求的表单数据)时,如果应用程序没有正确处理换行符的转换,可能会导致服务器解析错误。
某些文本编辑器在保存文件时,如果设计为遵循“标准”文本格式,可能会自动将 LF 转换为 CRLF。
网络传输中的 ASCII 码: HTTP 消息在网络上传输时,实际上是字节流。CR (ASCII 13) 和 LF (ASCII 10) 是特定的 ASCII 码。在传输过程中,如果某些网络设备(例如一些老旧的代理服务器或防火墙)对特定的 ASCII 码(例如 ` `)进行了不当的处理(例如将其视为某种控制命令或误解其含义),可能会引入问题。然而,CRLF 组合作为一个整体被广泛接受为行分隔符,并且在大多数情况下能够稳定传输。
兼容性权衡: 在 HTTP 协议设计的早期,兼容性是 paramount(最重要)的。考虑到当时市场份额和用户基础,选择一个能够与最广泛使用的操作系统(包括 Windows)兼容的分隔符是更安全的策略。

4. 现代视角:CRLF 的实际影响和处理

普遍接受的行业标准: 尽管 UNIX 的 LF 更简洁,但 CRLF 作为 HTTP 协议的行分隔符已经成为了一个事实上的行业标准。无论是 Web 服务器(Apache, Nginx, IIS)、Web 浏览器(Chrome, Firefox, Edge)、API 网关还是客户端库,都默认按照 CRLF 来解析 HTTP 消息。
文本文件格式的规范: RFC 2616 (HTTP/1.1 规范) 和后续的 RFC 7230 (HTTP/1.1 消息语法和路由) 等都明确规定,行分隔符是 CRLF。
跨平台兼容性处理: 现代操作系统和网络库已经非常成熟,能够很好地处理不同平台下的换行符差异。例如:
在 Linux/macOS 上,文本文件通常使用 LF。当这些系统生成 HTTP 请求时,通常会主动将内部表示的 LF 转换为 CRLF 以符合 HTTP 协议。
当从 Windows 客户端接收到包含 CRLF 的数据时,服务器端会正确解析。
在将文本内容嵌入到 HTTP 消息体中(例如表单提交)时,开发者通常会使用库函数来自动处理换行符的转换,以确保正确性。

总结来说,HTTP 协议之所以使用 Windows 的 CRLF 换行方式,而不是 UNIX 的 LF 换行方式,主要是基于以下原因:

1. 历史原因和操作系统兼容性: 在 HTTP 协议诞生的早期,MSDOS/Windows 操作系统占据重要地位,并且其文本处理习惯是 CRLF。选择 CRLF 是为了与当时最广泛使用的操作系统保持兼容。
2. 早期网络协议的惯例: FTP、SMTP 等早期网络协议也广泛使用 CRLF,HTTP 沿用了这一做法以保持一致性。
3. 技术实现上的考量: CRLF 被认为在当时能够更明确地指示行结束和归位,避免在某些终端上产生混淆。
4. 事实上的行业标准: 随着时间的推移,CRLF 作为 HTTP 的行分隔符已经成为一个根深蒂固的行业标准,几乎所有的实现都遵循这一规范。

虽然从纯粹的技术简洁性角度来看,LF 可能更优,但在协议设计的初期,兼容性和广泛性是更重要的考量因素,这最终导致了 CRLF 的确立。现代的开发工具和网络栈能够有效地处理这种差异,使得 CRLF 的使用不会对跨平台通信造成本质性的障碍。

网友意见

user avatar

此问题再一次证明了中国需要开一家古董电脑博物馆进行科普,不然年轻人将被半吊子“互联网”所鼓吹的“优雅”所蒙蔽,而视规范为“怪异冗长”。

下面是一台电传打字机,在PC机出现的主机时代,是最常见的人机界面,请看P键旁边的两个键,第一个键叫【LINE FEED】即LF,作用是将打印纸向上推动一行,第二个键叫【RETURN】,即Carriage return,简称CR,Carriage是指打印头小车,有些时候这个词也被写作Cartridge Return,即喷墨打印机里的墨盒Cartridge(跟我学绕口令:Print cartridge carriage is stalled),Carriage return翻译过来就是“小车回位”(将打印头小车推回行首),即“回车”。

如果要在电传打字机上完成现代电脑上“回车”的功能,需要按两下,一下【RETURN】一下【LINE FEED】,当然反过来理论上功能一样,而在电脑厂商的实施上更是随心所欲,任性如IBM就是用NL(NEXT LINE - 0x15)来做换行符。

正如 @贾物体 所说,在RFC158出现将命令统一为CR+LF,但很多厂商由于历史原因仍然不遵守,任性如苹果就在Mac OS X之前一直使用CR做换行符。

另外我们可以八卦一下为什么微软和大多数互联网标准用CRLF做换行符,1968年,13岁的比尔盖茨和15岁的保罗艾伦。他们当时使用的,就是上面那种Teletype Model 33电传打字机。

而他们使用的电脑主机并不在上面的照片里,根据历史资料,他们的学校当时有一台PDP-10,大概就是下面这个样子。(桌上的DEC Pack:快看我快看我,我是硬盘,还是移动硬盘哦!)

PDP是Digital Equipment Corporation,也就是Digital(DEC)公司的小型机系列,当时PDP系列小型机在商用和教育市场占有统治地位,它使用的TOPS-10系统就是使用CRLF作为【回车】的(Digital:怪我咯)。比尔盖茨学会BASIC语言的第二年,也就是1969年, 肯·汤普逊和丹尼斯·里奇两位大神才开始(在PDP-11上)开发Unix操作系统(PDP天天见),但Unix使用LF也不是两位大神拍脑袋的结论,而是沿用了MIT,通用电气和贝尔实验室联合开发的Multics的设计。同样是在1969年, ARPANET开始建设。

1971年,上面提到的RFC158标准确立,同年,贝尔实验室向外界公开了Unix,(Unix:对不起我来晚了)。

1972年,C语言被用来重写Unix

1975年微软成立,同年出现了RFC681标准,即Network Unix ,此时的Unix“展现了作为APRANET小型主机时的一些有趣功能”(present several interesting capabilities as an ARPANET mini-host)。

1977年的一张APRANET逻辑图,Digital的PDP小型机占据了统治地位,在1970年代,大多数的Internet相关的协议都已经诞生,包括电子邮件和FTP协议。这些协议都是用CRLF作为换行符。

当年的保罗艾伦是PDP电脑的大粉丝,1975年1月他和比尔盖茨在《大众电子》上看到Altair 8800,然后就着手把BASIC移植到这台新的微电脑上面去,然后保罗艾伦就把之前写的PDP-10平台Intel 8008模拟器和宏汇编工具拿出来一通魔改,两人就在哈弗大学的一台PDP-10上做出了Altair BASIC,成为了微软的第一款产品。后来Altair BASIC就成了Microsoft BASIC,再后来成了Visual Basic延续至今。

所以,这冗长而诡异的CRLF,还要归罪于Digital。(Digital:怪我咯,没有我你们别说互联网,连DOS都用不上~)

更多电脑情怀话题,请关注:古董电脑室

推荐阅读:美丽却被遗忘的UNIX硬件

user avatar

其实本质上是微软丢失了话语权,所以才搞成了Windows风格/Unix风格/Mac风格。


准确的说应该是传统风格/简洁风格/沙雕风格……

Windows是兼容简洁风格的。

user avatar

CRLF 才是正统啊,当时的打印机用的就是 CRLF

在 ASCII 的设计里,CR 表示把打印头移动到行首,LF 表示把打印头向下移动一行,两者联用才是「换行」的效果(CR 在前是因为打印头移动到行首时间比较长,所以放在前面)。

Multics 使用驱动来隔离设备区别,于是就单用一个 LF 了。

user avatar

正解在这里:Why is the line terminator CR+LF?

使用CR+LF的有RFC 0821 (SMTP)、RFC 1939 (POP)、RFC 2060 (IMAP)、RFC 2616 (HTTP)。其中SMTP的协议最早,时间是1982年8月。其中就已经要求了用<CRLF>。后来的HTTP,也是延续这个RFC的规则。

而Windows 1.0,是1985年的。所以说,这不是Windows的换行方式,而是RFC的标准换行方式,Dos/Windows执行了这个标准换行。

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有