IPv4 和 IPv6 的套接字位址結構

2021-09-02 20:54:22 字數 2887 閱讀 8125

大多數套接字函式都需要乙個指向套接字位址結構的指標作為引數,每個協議族都定義有它自己的套接字位址結構。這些結構的名字均以「sockaddr_」開頭,並以對應每個協議準的唯一字尾結尾。

ipv4 套接字位址結構通常也稱為「網際套接字位址結構」,它以「sockaddr_in」命名,定義在 標頭檔案中。下面是它的 posix 定義。

#include

struct in_addr;

struct sockaddr_in;

根據該定義,需要對套接字位址結構做幾點一般性的說明。

1、長度字段 sin_len 是為增加對 osi 協議的支援而隨 4.3 bsd-remo 新增的。正是因為有了該字段,才簡化了長度可變套接字位址結構的處理。並非所有的廠家都支援該欄位,而且 posix 規範也不要求有這個成員。

2、即使有長度字段,我們也無需設定和檢查它(除非涉及路由套接字),它是由處理來自不同協議族的套接字位址結構的例程(如路由表處理**)在核心中使用的(在源自 berkeley 的實現中,從程序到核心傳遞套接字位址結構的 4 個套接字函式(bind、connect、sendto 和 sendmsg)都要呼叫 sockargs 函式,該函式從程序複製套接字位址結構,並顯示地把它的 sin_len 字段設定成早先作為引數傳遞給這 4 個函式的該位址結構的長度。從核心到程序傳遞套接字位址結構的 5 個套接字函式(accept、recvfrom、recvmsg、getpeername 和 getsockname)均在返回到程序之前設定 sin_len 字段)。

3、posix 規範只需要這個結構中的 3 個字段:sin_family、sin_port 和 sin_addr。對於符合 posix 的實現來說,定義額外的結構欄位是可以接受的。另外,幾乎所有的實現都增加了 sin_zero 字段,所以所有的套接字位址結構大小都至少是 16 位元組。

4、在字段 s_addr、sin_family 和 sin_port 的 posix 資料型別中,in_addr_t 資料型別必須是乙個至少 32 位的無符號整數型別,in_port_t 必須是乙個至少 16 位的無符號整數型別,而 sa_family_t 可以是任何無符號整數型別。在支援長度欄位的實現中,sa_family_t 通常是乙個 8 位的無符號整數,而在不支援長度欄位的實現中,它則是乙個 16 位的無符號整數。下表列出了 posix 定義中常用的這種資料型別。

[img]

當作為任何套接字函式的引數時,套接字位址結構總是以引用形式來傳遞,所以這就要求對應的套接字函式必須處理來自所支援的任何協議族的套接字位址結構。為解決如何宣告所傳遞的指標的資料型別這一問題,在 ansi c 定義之前(那時還沒有「void *」這一通用的指標型別)所採取的辦法是定義乙個如下的通用套接字位址結構。

#include

struct sockaddr;

於是套接字函式就被定義成如下形式:

int bind(int, struct sockaddr *, socklen_t);

struct sockaddr_in serv; // ipv4 socket address structure.

/* fill in serv() */

bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));

從核心的角度看,使用指向通用套接字位址結構的指標另有原因:核心必須取呼叫者的指標,把它轉換成「struct sockaddr *」型別,然後檢查其中 sa_family 欄位的值來確定該結構的真實型別。而從應用程式開發人員的角度來看,這些通用套接字位址結構的唯一用途就是對指向特定於協議的套接字位址機構的指標執行強制型別轉換。要是「void *」指標型別可用就更簡單了,因為無須顯示進行型別轉換。

說完 ipv4 套接字位址結構,現在說說 ipv6 套接字位址結構。

#include

struct in6_addr;

#define sin6_len // required for compile-time tests

struct sockaddr_in6;

這裡需要注意以下幾點:

1、如果系統支援套接字位址結構中的長度字段,那麼 sin6_len 常量必須定義。

2、ipv6 的位址族是 af_inet6,而 ipv4 的是 af_inet。

3、結構中字段的先後順序做過編排,使得如果 sockaddr_in6 的結構本身是 64 位 對齊的,那麼 128 位的 sin6_addr 欄位也是 64 位對齊的。

4、sin6_flowinfo 字段分成兩部分:a) 低序 20 位是流標(flow label);b) 高序 12 位保留。

5、對於具備範圍的位址,sin6_scope_id 字段標識其範圍。最常見的是鏈路區域性位址的介面索引。

ipv6 套接字 api 中定義了一種新的通用套接字位址結構 sockaddr_storage,它克服了現有「struct sockaddr」的一些缺點,足以容納系統所支援的任何套接字位址結構。

#include

struct sockaddr_storage;

1、如果系統支援的任何套接字位址結構有對齊要求,那麼 sockaddr_storage 能夠滿足最苛刻的對齊要求。

2、sockaddr_storage 足夠大,能容納系統支援的任何套接字位址結構。

注意,除 ss_family 和 ss_len(如果有的話)外,sockaddr_storage 結構中的其他欄位對使用者來說都是透明的。sockaddr_storage 結構必須型別強制轉換成或複製到適合於 ss_family 欄位所給出位址型別的套接字位址結構中,才能訪問其他字段。

IPV4和IPV6的區別

internet的主機都有乙個唯一的ip位址,ip位址用乙個32位二進位制的數表示乙個主機號碼,但32位位址資源有限,已經不能滿足使用者的需求了,因此internet研究組織發布新的主機標識方法,即ipv6。在rfc1884中 rfc是request for comments document的縮寫...

IPv4和IPv6的區別

ipv4,是網際網路協議 internet protocol,ip 的第四版,也是第乙個被廣泛使用,構成現今網際網路技術的基石的協議。ipv6是下一版本的網際網路協議,也可以說是下一代網際網路的協議,它的提出最初是因為隨著網際網路的迅速發展,ipv4定義的有限位址空間將被耗盡,位址空間的不足必將妨礙...

IPv4和IPv6的區別

一 什麼是ipv4?ipv4是internet protocol version 4的縮寫,中文名為網際協議版本4。ipv4是一種無連線的協議。二 什麼是ipv6?三 ipv4和ipv6的區別?位址空間的區別。ipv4規定的位址長度是32位二進位制數字,而ipv6規定的位址長度是128位。位址表示方...