1. 程式人生 > >GUN C中的socket學習(一)

GUN C中的socket學習(一)

ipp 區分 如果 raw 文件表 一起 通訊 res 概念

  socket是用於通信的工具。

  套接字其實是一個廣義上的進程間通信的信道。就像pipe一樣,在GUN環境下socket也被用一個文件表示。不同的socket文件可以用於不同的進程間通信,甚至可以用來在網絡通信中不同主機之間的進程間通信(比如,我們的瀏覽器進程與某臺服務器上監聽80端口的進程通信完成web請求)。socket是與其他主機通信的主要手段,相關軟件有telnet, rlogin, ftp, talk 等。

  並不是所有的機器都支持socket通信,不過在GUN C庫中,頭文件<sys/socket.h>無論是否存在,socket函數總是可用的,不過在機器不支持時,這些函數總會失敗。

  1:socket套接字概念

    創建套接字時,必須指定通訊方式和通訊類型。創建socket時的協議決定了在套接字上發送和接收數據時的用戶級別的語義。socket通訊類型回答了一下問題:

      數據的傳輸單位是什麽?一些通信方式將數據視為較大結構的字節序列;其他人將字節分組成數據包

      數據在正常運行時可能丟失嗎? 一些通信方式保證發送的所有數據按照發送的順序到達(禁止系統或網絡崩潰); 其他樣式偶爾會丟失數據作為正常操作部分,有時可能會傳送數據包不止一次或錯誤的順序。設計使用不可靠通信方式的程序通常需要采取預防措施來檢測丟失或錯誤的數據包,並根據需要重新發送數據。

      是否需要啊建立連接?一些通訊方式要求必須建立起連接通道才可以通信,有的則不需要。

    當創建一個套接字時,還必須制定一個NAMESPACE,socket("address")也只有在特定命名空間的上下文中才有意義。事實上,甚至數據類型也可能取決於命名空間。命名空間也稱為“域”,也就是domain。但是我們應該避免使用這個詞,因為它可能會與其他感念混淆。每一個命名空間都有一個以“PF_”開頭的符號名稱。以“AF_”開頭的相應符號名稱指定該命名空間的地址格式。

    最後,在建立連接時必須制定使用的協議。該協議確定用於發送和接收數據的低級機制。每個協議對於特定的命名空間和通信風格是有效的;命名空間有時被稱為協議族,因為這是為什麽命名空間名稱以“PF_”開頭。

    協議的規則適用於兩個程序之間的數據傳遞,也許在不同的計算機上;大多數這些規則由操作系統處理,您不需要知道它們。需要了解的協議是什麽?

    為了在兩個socket之間進行通信,它們必須指定相同的協議。
    每個協議對於特定的樣式/命名空間組合是有意義的,不能與不適當的組合一起使用。例如,TCP協議僅適用於通信的字節流風格和Internet命名空間。
    對於風格和命名空間的每個組合,都有一個默認協議,您可以通過指定0作為協議號來請求。這就是通常應該做的 - 使用默認值。
  在以下各個地方的描述中,需要用於表示尺寸的變量/參數。這裏麻煩開始了。在第一個實現中,這些變量的類型只是int。在當時的大多數機器上,一個int是32位寬,這創建了一個事實上的標準,需要32位變量。這是重要的,因為這種類型的變量的引用被傳遞給內核。

    然後,POSIX組織來到並統一了界面,其中的“所有大小的值都是size_t”。在64位機器上,size_t是64位寬,所以不能再指向變量。

    Unix98規範通過引入一個類型socklen_t來提供一個解決方案。在POSIX更改為使用size_t的所有情況下都使用此類型。這種類型的唯一要求是它是至少32位的無符號類型。因此,需要傳遞對32位變量的引用的實現可以像使用64位值的實現。

  2:通訊方式

    GUN C庫包括對不同套接字的支持,每個套接字有不同的屬性。以下符號常量在<sys/socket.h>中定義

    宏:int SOCK_STREAM:這種方式就像是Pipes和FIFOs

    宏:int SOCK_DGRAM:用於不可靠的發送單獨尋址的數據包,與SOCK_STREAM相反。每次向這種套接字寫入數據時,該數據都會被打包成一個數據包。由於SOCK_DGRAM套接字沒有連接,因此必須在每個數據包指定收件人地址。

    系統對要傳輸的數據唯一的保證是,它會盡力傳遞每一個數據包。如果在第四個,第五個數據包出現故障之後,它可能成功發送第六個第七個數據包,第七個數據包可能在第六個數據包之前到達。SOCK_DGRAM的典型用途是在合理的時間內沒有看到響應的情況下簡單地重新發送數據包是可以接受的。點此查看詳情

    宏:int SOCK_RAW:這種風格提供對低級網絡協議和接口的訪問。普通用戶程序通常不需要使用這種風格。

  3:socket地址

    套接字的名稱通常稱為地址。用於處理套接字地址的函數和符號名稱不一致。有事使用術語“名稱”,有時稱為“地址”。可以講這些視為同義詞。

    使用socket函數創建一個套接字時沒有地址,其他進程只有給它一個地址時才可以找到與它通信。我們將這個過程稱為綁定到套接字,在C用使用bind函數實現。

    只需要關心套接字的地址,如果其他進程要找到它並開始與其通信。可以指定其他套接字的地址,但這通常是無意義的;首次從套接字發送數據,或者使用它來啟動連接時,如果沒有指定一個地址,系統會自動分配一個地址。

    偶爾,客戶端需要指定地址,因為服務器基於地址進行區分;例如,rsh和rlogin協議查看客戶端的套接字地址,只有在小於IPPORT_RESERVED(請參閱端口)時才會旁路密碼檢查。

    關於命名空間可以查閱Local Namespace和Internet Namespace。無論命名空間如何,都是用相同的bind、getsocketname來設置一個套接字的地址。在實際中,地址格式存在一些特定的數據結構中,當bind時將其轉換為struct sockaddr *。

GUN C中的socket學習(一)