通訊端與網路程式設計

位元組串流抽象(byte-stream abstraction)

想像用水管把一杯水倒進另一杯。你可能分三次潑進去,但在另一端,水是一道連續的水流出來——無從分辨哪一潑結束、下一潑從哪開始。TCP 連線傳遞你的資料正是如此:一道連續、有序的位元組串流,沒有內建的記號去分隔你送出的那些區塊。

具體來說,當你的程式呼叫 send 三次——比方先 100 位元組、再 50、再 30——TCP 並不保證接收端會讀到三次、分別是 100、50、30。核心可能把它們合併,在單一次 recv 中交付全部 180 位元組;也可能拆散到好幾次 recv,視時機、緩衝、網路狀況與 Nagle 演算法而定。TCP 唯一保證的是:每個位元組恰好抵達一次,且照你送出的順序。它可靠且有序,但沒有「訊息」的概念——你的應用程式那些邏輯單位之間的邊界,對它是看不見的。UDP 則相反:它保留訊息邊界,因為每個資料報都被當成一個單位交付。

為什麼重要:這一個事實是大量網路程式臭蟲的根源。因為 TCP 只是一道位元組串流,任何要交換離散訊息的應用——聊天協定、資料庫線路協定、HTTP 本身——都必須在其上加自己的訊息框架化,用長度前綴或分隔符,好讓接收端知道每則訊息從哪開始、到哪結束。假設「一次 send 等於一次 recv」的初學者,寫出的程式碼在 localhost 上能跑(那裡資料很少被拆),然後在真實網路負載下莫名其妙地壞掉。

用戶端接連送出兩行聊天訊息:先 "hello\n" 再 "world\n"。伺服器單一次 recv 可能一次回傳 "hello\nworld\n",甚至是 "hel" 再 "lo\nworld\n"。只有 \n 分隔符讓伺服器把它們拆回兩則訊息。

TCP 保證順序,不保證訊息邊界——那些得你自己加。

致命的假設:「一次 send 產生一次 recv。」並非如此。TCP 可以自由地合併或拆開你的寫入。忽視這點的程式碼常通過本機測試,卻在正式環境失敗。

又称
byte streamstream of bytesTCP byte stream位元組串流字節流