2.什麼是socket
你經常聽到人們談論著 “socket”,或許你還不知道它的確切含義。現在讓我告訴你:它是使用 標准Unix 文件描述符 (filedescriptor) 和其它程序通訊的方式。
什麼?
你也許聽到一些Unix高手(hacker)這樣說過:“呀,Unix中的一切就是文件!”那個家伙也許正在說到一個事實:Unix 程序在執行任何形式的I/O 的時候,程序是在讀或者寫一個文件描述符。一個文件描述符只是一個和打開的文件相關聯的整數。但是(注意後面的話),這個文件可能是一個網絡連接,FIFO,管道,終端,磁盤上的文件或者什麼其它的東西。Unix 中所有的東西就是文件!所以,你想和Internet上別的程序通訊的時候,你將要使用到文件描述符。你必須理解剛才的話。現在你腦海中或許冒出這樣的念頭:“那麼我從哪裡得到網絡通訊的文件描述符呢?”,這個問題無論如何我都要回答:你利用系統調用 socket(),它返回套接字描述符(socket descriptor),然後你再通過它來進行send() 和 recv()調用。
“但是...”,你可能有很大的疑惑,“如果它是個文件描述符,那麼為什 麼不用一般調用read()和write()來進行套接字通訊?”簡單的答案是:“你可以使用!”。詳細的答案是:“你可以,但是使用send()和recv()讓你更好的控制數據傳輸。”
存在這樣一個情況:在我們的世界上,有很多種套接字。有DARPA Internet 地址(Internet 套接字),本地節點的路徑名(Unix套接字),CCITT X.25地址 (你可以將X.25 套接字完全忽略)。也許在你的Unix 機器上還有其它的。我們在這裡只講第一種:Internet 套接字。
2.1 Internet 套接字的兩種類型
什麼意思?有兩種類型的Internet套接字?是的。不,我在撒謊。其實還有很多,但是我可不想嚇著你。我們這裡只講兩種。除了這些, 我打算另外介紹的"Raw Sockets" 也是非常強大的,很值得查閱。
那麼這兩種類型是什麼呢?一種是"Stream Sockets"(流格式),另外一種是"DatagramSockets"(數據包格式)。我們以後談到它們的時候也會用到 "SOCK_STREAM" 和 "SOCK_DGRAM"。數據報套接字有時也叫“無連接套接字”(如果你確實要連接的時候可以用connect()。) 流式套接字是可靠的雙向通訊的數據流。如果你向套接字按順序輸出“1,2”,那麼它們將按順序“1,2”到達另一邊。它們是無錯誤的傳遞的,有自己的錯誤控制,在此不討論。
有什麼在使用流式套接字?你可能聽說過 telnet,不是嗎?它就使用流式套接字。你需要你所輸入的字符按順序到達,不是嗎?同樣,WWW浏覽器使用的 HTTP協議也使用它們來下載頁面。實際上,當你通過端口80 telnet 到一個 WWW 站點,然後輸入 “GET pagename” 的時候,你也可以得到 HTML 的內容。為什麼流式套接字可以達到高質量的數據傳輸?這是因為它使用了“傳輸控制協議 (The Transmission Control Protocol)”,也叫 “TCP” (請參考 RFC-793 獲得詳細資料。)TCP控制你的數據按順序到達並且沒有錯誤。你也許聽到 “TCP” 是因為聽到過 “TCP/IP”。這裡的 IP 是指“Internet 協議”(請參考 RFC-791。) IP 只是處理 Internet 路由而已。
那麼數據報套接字呢?為什麼它叫無連接呢?為什麼它是不可靠的呢?有這樣的一些事實:如果你發送一個數據報,它可能會到達,它可能次序顛倒了。如果它到達,那麼在這個包的內部是無錯誤的。數據報也使用 IP 作路由,但是它不使用TCP。它使用“用戶數據報協議 (User Datagram Protocol)”,也叫 “UDP” (請參考 RFC-768。)
為什麼它們是無連接的呢?主要是因為它並不象流式套接字那樣維持一個連接。你只要建立一個包,構造一個有目標信息的IP 頭,然後發出去。無需連接。它們通常使用於傳輸包-包信息。簡單的應用程序有:tftp, bootp等等。
你也許會想:“假如數據丟失了這些程序如何正常工作?”我的朋友,每個程序在 UDP 上有自己的協議。例如,tftp 協議每發出的一個被接受到包,收到者必須發回一個包來說“我收到了!” (一個“命令正確應答”也叫“ACK” 包)。如果在一定時間內(例如5秒),發送方沒有收到應答,它將重新發送,直到得到 ACK。這一ACK過程在實現 SOCK_DGRAM 應用程序的時候非常重要。
摘自 xiaobin_HLJ80的專欄