天天看點

兩種Internet Socket

難道隻有兩種​

​Internet Socket​

​嗎?

開玩笑的啦,當然遠不止兩種喽。但是為了怕吓到你,這裡主要介紹​

​Stream Sockets​

​​以及​

​Datagram Sockets​

​​。除此之外,​

​Raw Sockets​

​(原始套接字)也是一種功能更加強大的Socket,如果感興趣,你可以查一查資料了解一下。

兩種Internet Socket

如果要進行網絡通信,我們要做的第一件事肯定是調用​

​socket()​

​​函數,并指定想使用的套接字類型,比如​

​SOCK_STREAM​

​​、​

​SOCK_DGRAM​

​​、​

​SOCK_RAW​

​​等類型,他們分别表示​

​Stream Sockets​

​​、​

​Datagram Sockets​

​​以及​

​Raw Sockets​

​。

我們先從​

​Stream Sockets​

​說起。

Stream Sockets

​Stream sockets​

​是一種可靠的、支援雙向連接配接的通信流。

如果你以“1,2”的順序将這串數字發送到socket中,那麼在接收端就會以同樣的順序接受到“1,2”,肯定不會出錯。

哪裡會用到​

​Stream sockets​

​呢?

或許你聽說過​

​telnet​

​​程式?​

​telnet​

​​用的就是​

​Stream sockets​

​,你輸入的每個字元都必須按照你的輸入順序依次抵達,要不然指令肯定就錯亂了不是?

同樣,浏覽器使用的​

​HTTP​

​​協定底層也使用了​

​Stream sockets​

​​來擷取網頁資訊。如果你通過80端口​

​telnet​

​​到一個網站,并輸入 "​

​GET / HTTP/1.0​

​",然後按兩下Enter,你就會收到網站發送給你的 HTML !

​Stream sockets​

​ 是怎麼做到如此高品質地傳輸資料的呢?

​Stream sockets ​

​​底層使用了 "The Transmission Control Protocol"(傳輸控制協定),就是大名鼎鼎的 "​

​TCP​

​​"(TCP 的全部細節可以參考RFC 793)。

​TCP ​

​​會確定你的資料可以按照順序抵達而且不會出錯。你之前可能是從"​

​TCP/IP​

​​"這個專業名詞中聽說的​

​TCP​

​​,其中的​

​IP​

​​ 是指 "Internet Protocol"(網絡協定,詳見 RFC 791​)。​

​IP​

​ 主要處理資料在各個節點之間的Internet routing(網絡路由),通常不保障資料的完整性。

Datagram Sockets

​Datagram sockets​

​ 有時候被叫做 “connectionless sockets”(無連接配接的sockets),而且,這玩意通常也不怎麼可靠!

為啥?

因為​

​Datagram Sockets​

​​底層用的是“User Datagram Protocol”(使用者資料報協定,詳見RFC 768​),也就是“​

​UDP​

​”。

​UDP​

​​并不像​

​TCP​

​那樣會直接在傳輸層将資料量過大的消息分片(TCP segments),而是會在IP層被動進行分包,将一個IP packet分包成多個IP fragments。這樣一來,接收端就必須做IP fragments的重組,合并為原來的IP packet,這無疑增加了資料包丢失的機率。(其實分包倒還好,主要是UDP沒有TCP那麼強大的糾錯能力)

如果你發送了一個 ​

​datagram​

​(UDP的資料報),它可能會順利抵達、但可能不會按照發送順序抵達。

譯者注:下文将稱UDP發送的資料為datagram,之後提到這個詞就意味着使用的是UDP協定

那為什麼又會被稱為“無連接配接的sockets”呢?

因為​

​Datagram Sockets​

​​不用像​

​Stream Sockets​

​一樣維持雙方的連接配接,我們隻需要把需要發送的資料打包,給它一個目的地資訊,然後發送出去就行了。

是以當​

​TCP​

​​協定不可用,或者你很确定丢幾個資料包不至于惹什麼大亂子的情況下,不妨使用​

​datagram socket​

​​。這樣的使用場景有很多,比如​

​tftp​

​​(trivial file transfer protocol,簡易檔案傳輸協定,是 ​

​FTP​

​ 協定的小兄弟),多人遊戲以及視訊會議等。

事情有點不太對勁!​

​tftp​

​可是進行檔案傳輸的協定啊,如果傳輸過程中丢包了,客戶根本沒法正常使用啊。

沒錯!​

​UDP​

​​是不可靠的,但是我們可以在​

​UDP​

​​的上層使用可靠的應用層協定,就比如​

​tftp​

​​協定。​

​tftp ​

​​協定會死死盯着自己發送的每個資料包,要求接受方必須回複一個資料包來表示"我收到了!"(一個"​

​ACK​

​​"回複資料包)。如果發送方在5秒内沒有收到​

​ACK​

​​,表示它該重傳這個資料包,直到收到 ​

​ACK ​

​​為止。在不可靠的​

​UDP​

​​上建構可靠的​

​SOCK_DGRAM​

​​應用程式,這種​

​ACK​

​機制非常值得借鑒。