套接字地址結構
大多數套接字函式都需要一個指向套接字地址結構的指標作為引數。每個協議族都定義了它自己的套接字地址結構。這些結構的名字均以sockaddr_開頭,並以對應每個協議族的唯一字尾結尾。
1、IPv4套接字地址結構
IPv4套接字地址結構通常也稱為“網際套接字地址結構”,它以sockaddr_in命名,定義在<netinet/in.h>標頭檔案中。圖1給出了它的POSIX定義:
struct in_addr {
in_addr_t s_addr; /* 32-bit IPv4 address */
/* network byte ordered */
};
struct sockaddr_in {
uint8_t sin_len; /* length of structure (16) */
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* 16-bit TCP or UDP port number */
/* network byte ordered */
struct in_addr sin_addr; /* 32-bit IPv4 address */
/* network byte ordered */
char sin_zero[8]; /* unused */
};
圖1 網際(IPv4)套接字地址結構:sockaddr_in
利用圖1所示的例子,我們對套接字地址結構做幾點一般性的說明:
•長度欄位sin_len是為增加對OSI協議的支援而隨4.3BSD-Reno新增的。在此之前,第一個成員是sin_family,它是一個無符號短整數(unsigned short)。並不是所有的廠家都支援套接字地址結構的長度欄位,而且POSIX規範也不要求有這個成員。
•即使有長度欄位,我們也無須設定和檢查它,除非涉及路由套接字。它是由處理來自不同協議族的套接字地址結構的例程(例如路由表處理程式碼)在核心中使用的。
•POSIX規範只需要這個結構中的3個欄位:sin_family、sin_addr和sin_port。對於符合POSIX的實現來說,定義額外的結構欄位是可以接受的,這對於網際套接字地址結構來說也是正常的。幾乎所有的實現都增加了sin_zero欄位,所以所有的套接字地址結構大小都至少是16位元組。
•我們給出了欄位s_addr、sin_family和sin_port的POSIX資料型別。in_addr_t資料型別必須是一個至少32位的無符號整數型別,in_port_t必須是一個至少16位的無符號整數型別,而sa_family_t可以是任何無符號整數型別。在支援長度欄位的實現中,sa_family_t通常是一個8位的無符號整數,而在不支援長度欄位的實現中,它則是一個16位的無符號整數。圖2列出了POSIX定義的這些資料型別。
圖2 POSIX規範要求的資料型別
•IPv4地址和TCP或UDP埠號在套接字地址結構中總是以網路位元組序來儲存。
•sin_addr欄位是一個結構,而不僅僅是一個in_addr_t型別的無符號長整數,這是有歷史原因的。早期的版本(4.2BSD)把in_addr結構定義為多種結構的聯合(union),允許訪問一個32位IPv4地址中的所有4個位元組,或者訪問它的2個16位值。這用在地址被劃分成A、B和C三類的時期,便於獲取地址中的適當位元組。然而隨著子網劃分技術的來臨和無類地址編排的出現,各種地址類正在消失,那個聯合已不再需要了。如今大多數系統已經廢除了該聯合,轉而把in_addr定義為僅有一個in_addr_t欄位的結構。
•sin_zero欄位未曾使用,不過在填寫這種套接字地址結構時,我們總是把該欄位置為0。按照慣例,我們總是在填寫前把整個結構置為0,而不是單單把sin_zero欄位置為0。儘管多數使用該結構的情況不要求這一欄位為0,但是當捆綁一個非通配的IPv4地址時,該欄位必須為0。
2、通用套接字地址結構
當作為一個引數傳遞進任何套接字函式時,套接字地址結構總是以引用形式(也就是以指向該結構的指標)來傳遞。然而以這樣的指標作為引數之一的任何套接字函式必須處理來自所支援的任何協議族的套接字地址結構。
在如何宣告所傳遞指標的資料型別上存在一個問題。有了ANSI C後解決辦法很簡單:void*是通用的指標型別。然而套接字函式是在ANSI C之前定義的,在1982年採取的辦法是在<sys/socket.h>標頭檔案中定義一個通用的套接字地址結構,如圖3所示:
struct sockaddr {
uint8_t sa_len;
sa_family_t sa_family; /* address family: AF_XXX value */
char sa_data[14]; /* protocol-specific address */
};
圖3 通用套接字地址結構:sockaddr
於是套接字函式被定義為以指向某個通用套接字地址結構的一個指標作為其引數之一,這正如bind函式的ANSI C函式原型所示:
int bind(int, struct sockaddr *, socklen_t);
3、值-結果引數
1)從程式到核心傳遞套接字地址結構的函式有3個:bind、connect和sendto。這些函式的一個引數是指向某個套接字地址結構的指標,另一個引數是該結構的整數大小,例如:
struct sockaddr_in serv;
/* fill in serv{} */
connect(sockfd, (struct sockaddr*)&serv, sizeof(serv));
2)從核心到程式傳遞套接字地址結構的函式有4個:accept、recvfrom、getsockname和getpeername。這4個函式的其中兩個引數是指向某個套接字地址結構的指標和指向表示該結構大小的整數變數的指標。例如:
struct sockaddr_in cli;
socklen_t len;
len = sizeof(cli);
getpeername(sockfd, (struct sockaddr*)&cli, &len);
/* len may have changed */
把套接字地址結構大小這個引數從一個整數改為指向某個整數變數的指標,其原因在於:當函式被呼叫時,結構大小是一個值,它告訴核心該結構的大小,這樣核心在寫該結構時不至於越界;但函式返回時,結構大小又是一個結果,它告訴程式核心在該結構中究竟儲存了多少資訊。這種型別的引數稱為值-結果引數。
相關文章
- UNIX網路程式設計(6)--套接字地址結構、通用套接字地址結構程式設計
- 套接字socket 的地址族和型別、工作原理、建立過程型別
- IPC之套接字
- 網路套接字
- Linux :套接字Linux
- 《UNIX網路程式設計》筆記 - 套接字選項/UDP套接字程式設計筆記UDP
- IP地址結構
- python套接字基本使用Python
- Socket套接字通訊原理
- Java套接字程式設計Java程式設計
- 學習--原始套接字(轉)
- 已知結構體成員地址獲取結構體首地址結構體
- TCP套接字繫結雙埠傳輸檔案(python)TCPPython
- python UDP套接字通訊PythonUDP
- Python 套接字內建方法Python
- Java網路通訊套接字Java
- Linux/UNIX套接字連線Linux
- nginx取結構體地址Nginx結構體
- 基本TCP套接字程式設計APITCP程式設計API
- nginx建立和監聽套接字分析Nginx
- Python原始套接字程式設計Python程式設計
- 20.7 OpenSSL 套接字SSL加密傳輸加密
- 計算機網路之十一:套接字Socket計算機網路
- 14.1 Socket 套接字程式設計入門程式設計
- 安全套接字層證書是什麼
- SO_REUSEADDR 套接字選項應用
- 5.1.3 非塞模式套接字的優勢和不足模式
- C# 2.0 套接字程式設計例項初探程式設計
- Linux網路程式設計--原始套接字(轉)Linux程式設計
- Oracle叢集技術 | OLR與套接字檔案(二)Oracle
- 【T05】套接字介面比XTI_TLI更好用
- Linux 下的程式間通訊:套接字和訊號Linux
- Oracle 叢集的自啟動,OLR與套接字檔案Oracle
- [單刷 APUE 系列] 第十六章——網路 IPC:套接字
- Java學習筆記-----從套接字中讀寫資料Java筆記
- 數學是結構,不是數字!
- C++關於DLL中建立套接字的問題(求教)C++
- Linux中什麼是套接字檔案?有什麼作用?Linux