為什麼在 HTTP 協議中,使用的是 Windows 換行方式而不是 UNIX 換行方式?

在 Web 的發展過程中,UNIX 系統從一開始到現在一直是主要的開發和運行平台,但是在 HTTP 協議中,各個 header 之間用的卻是 CRLF (
)這樣的 Windows/DOS 換行方式,而不是 UNIX 普遍的的 LF (
)換行方式,看上去十分冗長和詭異,為什麼會這樣?


在評論里給 @Belleve 補充了一下,又仔細看了一遍他的回答,發現他說的是 ASCII。

的確 CR-LF 是正統,來自 ASCII,而 ASCII 沿襲了電傳打字機的設計;電傳打字機又沿襲了傳統的機械打字機的設計。

而機械打字機是這樣的:

看見左側墨帶盒上邊的金屬手柄了么?那玩意就是換行手柄。

打完一行字之後,滾筒已經基本移出了打字機主體,需要推左手邊的換行手柄,然後滾筒會被推到最右邊,打字頭對準了行首,這就是 CR。

推到頭之後,繼續用力,換行手柄大約會被扳動30度左右,這時候你會發現紙往上卷了一行(具體多少根據你設置的行距決定),這就是 LF。

所以遵循傳統,ASCII 設計了 CR-LF 順序。

這類設計,幾十年之後被稱為擬物化


CRLF 才是正統啊,當時的印表機用的就是 CRLF

在 ASCII 的設計里,CR 表示把列印頭移動到行首,LF 表示把列印頭向下移動一行,兩者聯用才是「換行」的效果(CR 在前是因為列印頭移動到行首時間比較長,所以放在前面)。

Multics 使用驅動來隔離設備區別,於是就單用一個 LF 了。


正解在這裡:Why is the line terminator CR+LF?

使用CR+LF的有RFC 0821 (SMTP)、RFC 1939 (POP)、RFC 2060 (IMAP)、RFC 2616 (HTTP)。其中SMTP的協議最早,時間是1982年8月。其中就已經要求了用&。後來的HTTP,也是延續這個RFC的規則。

而Windows 1.0,是1985年的。所以說,這不是Windows的換行方式,而是RFC的標準換行方式,Dos/Windows執行了這個標準換行。


此問題再一次證明了中國需要開一家古董電腦博物館進行科普,不然年輕人將被半吊子「互聯網」所鼓吹的「優雅」所蒙蔽,而視規範為「怪異冗長」。

下面是一台電傳打字機,在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 LF 的語義跟 RFC 標準的 CRLF 是不同的。

Unix LF 的語義是行結束符。換句話說 LF 是行的一部分。一個文件的最後一行也需要以 LF 結束,否則是個非法的文本文件。一個文件有單個 LF 結尾是正常結束,如果一個文本文件末尾有個空行,我們應該看到兩個 LF 。

RFC 的 CRLF 是換行符,它是兩行之間的分隔,不是行內容的一部分,因此一個正常文本文件的最後一行結尾不應該出現 CRLF,如果出現了單個的 CRLF 意味著末尾是個空行。

簡單說,CRLF 是行分隔符,UnixLF是行結束符。互聯網規範的定義中需要的是行分隔符而非行結束符。所以用 CRLF。


Unix才是不遵守當時已有規範。其實當時KR他們兩個人為了節省一個位元組,才把CRLF精簡成LF了。


因為Windows才是遵循了標準的那個啊。。。


來源於網路

關於「回車」(carriage return)和「換行」(line feed)這兩個概念的來歷和區別。

在計算機還沒有出現之前,有一種叫做電傳打字機(Teletype Model 33)的玩意,每秒鐘可以打10個字元。但是它有一個問題,就是打完一行換行的時候,要用去0.2秒,正好可以打兩個字元。要是在這0.2秒裡面,又有新的字元傳過來,那麼這個字元將丟失。

於是,研製人員想了個辦法解決這個問題,就是在每行後面加兩個表示結束的字元。一個叫做「回車」,告訴打字機把列印頭定位在左邊界;另一個叫做「換行」,告訴打字機把紙向下移一行。

這就是「換行」和「回車」的來歷,從它們的英語名字上也可以看出一二。

後來,計算機發明了,這兩個概念也就被般到了計算機上。那時,存儲器很貴,一些科學家認為在每行結尾加兩個字元太浪費了,加一個就可以。於是,就出現了分歧。

Unix系統里,每行結尾只有「&<換行&>」,即「
」;

Windows系統裡面,每行結尾是「 &<回車&>&<換行&>」,即「
」;

Mac系統里,每行結尾是「&<回車&>」。

windows下enter是
,unix下是
,mac下是

一個直接後果是,Unix/Mac系統下的文件在Windows里打開的話,所有文字會變成一行;而Windows里的文件在Unix/Mac下打開的話,在每行的結尾可能會多出一個^M符號

所以unix的文本到windows會出現換行丟失(ultraedit這種軟體可以正確識別); 而反過來就會出現^M的符號了

Windows等操作系統用的文本換行符和UNIX/Linux操作系統用的不同,Windows系統下輸入的換行符在UNIX/Linux下不會顯示為「換行」,而是顯示為 ^M 這個符號(這是Linux等系統下規定的特殊標記,佔一個字元大小,不是 ^ 和 M 的組合,列印不出來的)。Linux下很多文本編輯器(命令行)會在顯示這個標記之後,補上一個自己的換行符,以避免內容混亂(只是用於顯示,補充的換行符不會寫入文件,有專門的命令將Windows換行符替換為Linux換行符)。 UNIX/Linux系統下的換行符在Windows系統的文本編輯器中會被忽略,整個文本會亂成一團。

windows換行是
,十六進位數值是:0D0A。

LINUX換行是
,十六進位數值是:0x0A

所以在linux保存的文件在windows上用記事本看的話會出現黑點,我們可以在LINUX下用命令把linux的文件格式轉換成win格式的。

unix2dos 是把linux文件格式轉換成windows文件格式

dos2unix 是把windows格式轉換成linux文件格式。

linux下刪除windows換行符^M

OJ判題時發現一個問題:用%c讀入的代碼都會報wa。後來發現跟scanf有關。在linux下使用%c會讀到

兩個字元。所以需要將^M(也就是
)字元刪掉

刪除方法不少。找了一個比較簡單的。

要將a.txt里的^M去掉並寫入b.txt,則使用如下指令cat a.txt | tr -d "^M" &> b.txt

注意:語句中的^M是通過ctrl+V, ctrl+M輸入的。特指/r字元

unix 下換行符只有:

Dos 下換行符有:

具體的,
的ascii 碼是:14

的ascii 碼是:10


CRLF 的換行方式的確是源自打字機,但是這並不能解釋為什麼 HTTP 協議採用了 CRLF 這種換行方式。

換行的表示方式有四種,分別是 CRLF (
),LFCR (

),CR (
) 和 LF (
)。用 CRLF 可以說是繼承正統,但也可以說是個歷史遺留問題。

在設計 HTTP 協議的年代,CRLF 是規範。如果現在不考慮任何歷史包袱,重新設計 HTTP 協議的話,LF 應該會成為標準。不過 HTTP 標準也說了,建議同時支持 LF 這種換行方式,所以在實際應用上也沒什麼影響。

This EOL convention was the core of the initial Telnet protocol
definition (negotiated options were added later). Jon Postel was
one of the principal protocol policemen enforcing the CR LF
requirement. He carried the EOL = CR LF convention Telnet into
FTP and SMTP on the ARPAnet, and later these protocols were taken
essentially unchanged into the Internet.

https://www.rfc-editor.org/old/EOLstory.txt

CR-LF as newline is the Internet standard, which long predates HTTP; I believe it was originally specified as part of TELNET in RFC 158 in 1971. The RFC Editor has a page explaining some of the history. This is the convention used by other Internet protocols such as FTP and SMTP, so it only makes sense for HTTP to be consistent with them.

why does http use CRLF as line delimiter?


補充點個人看法,HTTP消息體的格式基本繼承於電子郵件的MIME消息格式,電子郵件當中消息的每個部分都是用CR-LF作為結束符,而消息體內部的換行用LF,防止混淆。這樣對當時的從業人來說頭部用CR-LF應該是很正常的事情吧。

==============================================

呃好像說錯了,如果說MIME的話,電子郵件當中的MIME是LF分隔的……整個電子郵件結束是一個CRLF。SMTP協議差不多是每行命令一個CRLF,然後整個電子郵件是一個MIME消息體,一個CRLF。


我來補充什麼是CR-LF而不是LF-CR。這是電傳打字機的設計細節。一是因為最早CR有延遲,LF沒有(後來有了高速機型就都沒有了——準確說延遲都在字元時隙以下了),同時CR和LF完全是兩套機械系統控制。另外就是隔行列印需要CR-LF-LF…。先CR可利用等待的時間完成LF,同時連續多個LF可以優化機械實現。於是先執行CR就順理成章成為標準了。


使用的既不是Windows的也不是UNIX的。

標準化HTTP協議的是互聯網工程任務組,它最早標準化的協議比Windows和UNIX出現的都早。一旦前面用了什麼樣的約定,後面出現的協議沒有理由不用相同的約定。


回車+換行

打字機風格!


ASCII was developed simultaneously by the ISO and the ASA, the predecessor organization to ANSI. During the period of 1963–1968, the ISO draft standards supported the use of either CR+LF or LF alone as a newline, while the ASA drafts supported only CR+LF.


http://ipn.li/kernelpanic/46/ 聽下播客吧

話說 APUE書一開始就講了


推薦閱讀:

C/C++語言在Windows下服務端開發,有哪些開源項目?
哪些事情是 Windows 能做但 OS X 不能做的?
如何評價Remix OS?以及未來對安卓平板的影響?
win10怎樣去掉下面兩個提示?「無法使用內置管理員賬戶打開」 「你需要提供管理員許可權才能刪除此文件」

TAG:MicrosoftWindows | Unix | HTTP | Web伺服器 |