首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Beej's Guide 系列連載 05:位元組序轉換與進階 Socket 結構體

     編輯:關於C語言

位元組序轉換函式

網路序 = Big-Endian。主機序視 CPU 而定。四大轉換函式:

uint16_t htons(uint16_t hostshort);  // Host to Network Short
uint32_t htonl(uint32_t hostlong);   // Host to Network Long
uint16_t ntohs(uint16_t netshort);   // Network to Host Short
uint32_t ntohl(uint32_t netlong);    // Network to Host Long

鐵律:所有放入 sockaddr 結構的 sin_port、sin_addr.s_addr 必須經 htons/htonl 轉換。

struct addrinfo 詳解

現代 Socket 程式設計的核心結構,支援 IPv4/IPv6 協議無關寫法。欄位包括 ai_family、ai_socktype、ai_protocol、ai_addr (指向 sockaddr)、ai_next (鏈表)。由 getaddrinfo() 填充,用畢需 freeaddrinfo() 釋放。

struct sockaddr 家族

通用基址

struct sockaddr {
    sa_family_t sa_family;  // AF_INET, AF_INET6
    char        sa_data[14]; // 14 bytes protocol address
};

IPv4 專用 sockaddr_in

struct sockaddr_in {
    sa_family_t    sin_family; // AF_INET
    in_port_t      sin_port;   // 網路序 port
    struct in_addr sin_addr;   // IPv4 位址
    unsigned char  sin_zero[8]; // 填充對齊
};
struct in_addr { uint32_t s_addr; };

使用時:memset(&sin, 0, sizeof(sin)) 或 bzero 清零,再填欄位。

IPv6 專用 sockaddr_in6

struct sockaddr_in6 {
    sa_family_t     sin6_family;   // AF_INET6
    in_port_t       sin6_port;
    uint32_t        sin6_flowinfo;
    struct in6_addr sin6_addr;     // 128-bit
    uint32_t        sin6_scope_id; // 介面範圍 ID
};
struct in6_addr { unsigned char s6_addr[16]; };

通用儲存 sockaddr_storage

struct sockaddr_storage {
    sa_family_t ss_family;
    char        __ss_padding[128-sizeof(sa_family_t)];
    __ss_align; // 強制對齊
};

足以容納 IPv4/IPv6 任何地址。用於 accept()、recvfrom() 等輸出參數,事後檢查 ss_family 決定轉型為 sockaddr_in* 或 sockaddr_in6*。

實務提醒

  • 永遠用 getaddrinfo() 取代 gethostbyname() / inet_addr()。
  • sin_zero / __ss_padding 必須清零,否則可能導致比較錯誤。
  • IPv6 連結本地位址需指定 sin6_scope_id(介面索引)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved