天天看點

套接字程式設計簡介(一)套接字地位址結構套接字位址結構的比較  值——結果參數

套接字地位址結構

  •  IPv4套接字位址結構
1 struct in_addr{
 2       in_addr_t   s_addr;  // 32位的IPv4位址     
 3 }
 4 
 5 struct sockaddr_in{
 6       uint_8  sin_len;  // 長度
 7       sa_family_t   sin_family;  //協定族,IPv4為AF_INET
 8       in_port_t   sin_port;    // 端口号
 9       struct  in_addr   sin_addr;  //IPv4位址
10       char    sin_zero[8];    //未曾用過
11 }
           
  • 通用套接字位址結構
1 struct sockaddr{
2     uint8_t   sa_len;  
3     sa_family  sa_family; //訓示協定族
4     char     sa_data[14]; //特定協定位址
5 }
           

        當作為一個參數傳遞任何套接字函數時,套接字位址總是以引用形式(也就是以指向該結構的指針)來傳遞。

        int bind(int,struct sockaddr *,socklen_t)

        對這些函數的任何調用都必須要将指向特定于協定的套接字位址結構的指針進行類型強制轉換,變成指向某個通用套接字位址結構的指針。eg:

        struct sockaddr_in serv;       

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

        如果省略了其中的類型強制轉換部分 ,會有警告資訊("warning: passing arg 2 of '"bind" from incompatible pointer type. ")

        從應用程式開發人員的觀點看,這些通用套接字位址結構的唯一用途是 對指向特定于協定的套接字位址結構的指針執行類型強制轉換。

套接字程式設計簡介(一)套接字地位址結構套接字位址結構的比較  值——結果參數
  •  iPv6位址結構
//IPV6套接字位址結構,在<netinet/in.h>頭檔案中定義

struct in6_addr
{
    uint8_t s6_addr[16];    //128位的IP位址
};
#define SIN6_LEN    
struct sockaddr_in6{
    uint8_t sin6_len;    //長度字段,如果系統支援這個字段,那麼這個字段必須定義
    sa_family_t sin6_family;    //AF_INET6.位址族
    in_port_t sin6_port;    //端口号,
    uint32_t sin6_flowinfo;    //流資訊,低20位是流标準,高20位保留
    struct in6_addr sin6_addr;    //IP位址
    uint32_t sin6_scope_id;    // 作用域的接口集
};
           

* 若系統支援套接字位址結構中的長度字段,則 SIN6_LEN 常值必須定義;

* sin6_flowinfo 字段分成兩個字段:低序 20 位是流标,高序 12 位保留;

* 對于具備範圍的位址,sin6_scope_id 字段辨別其範圍;

  •  新的通用套接字位址結構
struct sockaddr_storage{
 
    uint8_t         ss_len;     /* length of this struct (implementation dependent) */
    sa_family_t     ss_family;  /* address family: AF_xxx value */
    /* implementation-dependent elements to provide:
     * 1) alignment sufficient to fulfill the alignment requirments of all socket address types that the system supports. 
     * 2) enough storage to hold any type of socket address that the system suports.
     */
};
           

  sockaddr_storage類型提供的通用套接字位址結構相比sockaddr存在以下兩種差别。

        若系統支援任何套接字位址結構有對齊需要,則該新通用位址結構能夠滿足最苛刻的對齊要求;

        sockaddr_torage足夠大,新位址結構能夠容納系統支援的任何套接字位址結構;

套接字位址結構的比較
套接字程式設計簡介(一)套接字地位址結構套接字位址結構的比較  值——結果參數

值——結果參數

        當往一個套接字函數傳遞一個套接字位址結構時,該結構總是以引用形式來傳遞,也就是說傳遞的是指向該結構的一個指針。該結構的長度也作為一個參數來傳遞,但傳遞方式取決于該結構的傳遞方向:從程序到核心,還是從核心到程序

        1. 從程序到核心傳遞套接字位址結構函數有3個:bind connect sendto

             這些函數 一個參數是指向某個套接字位址結構的指針 另一個參數是該結構的整數大小

        eg: struct sockaddr_in serv;

                 connect ( sockfd,(SA *) &serv , sizeof(serv) )

套接字程式設計簡介(一)套接字地位址結構套接字位址結構的比較  值——結果參數
注意:套接字位址結構大小的資料類型實際上是 socklen_t 而不是 int

        2. 從核心到程序傳遞套接字結構的函數有4 個 : accept ,recvfrom,getcsockname,getpeername

          這四個函數中的其中兩個參數是指向某個套接字位址結構的指針和指向表示該結構大小的整數變量的指針。eg:

        struct sockaddr_un cli;

        socklen_t len;

        len = sizeof(cli);       

        getpeername(unixfd , ( SA  *)  &cli, &len);        /* len may have chan

把套接字位址結構大小這個參數從一個整數改為指向某個整數變量的指針  其原因在于:

        當函數被調用時,結構大小是一個值,它告訴核心該結構的大小,這樣核心在寫該結構時不至于越界;

        當函數傳回時,結構大小又是一個結果,它告訴核心在該結構中究竟存儲了多少資訊 這種類型的參數稱為 值--結果參數

套接字程式設計簡介(一)套接字地位址結構套接字位址結構的比較  值——結果參數

         當使用值--結果從哪書作為套接字位址結構的長度時,

        如果套接字位址結構是固定長度的,那麼從核心傳回的值總是那個固定長度。eg:IPv4 的sockaddr_in長度是16 ,IPv6的sockaddr_in6長度是28

        若是可變長度的 ,eg:Unix域的sockaddr_un 傳回值可能小于該結構的最大長度