難道隻有兩種
Internet Socket
嗎?
開玩笑的啦,當然遠不止兩種喽。但是為了怕吓到你,這裡主要介紹
Stream Sockets
以及
Datagram Sockets
。除此之外,
Raw Sockets
(原始套接字)也是一種功能更加強大的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
機制非常值得借鑒。