簡體   English   中英

sockaddr,sockaddr_in和sockaddr_in6有什么區別?

[英]What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?

我知道sockaddr_in用於IPv4,sockaddr_in6用於IPv6。 我的困惑是sockaddr和sockaddr_in之間的區別[6]。

有些函數接受sockaddr ,有些函數接受sockaddr_insockaddr_in6 ,所以:

  • 規則是什么?
  • 為什么需要兩種不同的結構?

並且因為sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)

  • 這是否意味着如果我們需要支持ipv4和ipv6,我們應該總是使用sockaddr_in6在堆棧中分配內存並轉換為sockaddr和sockaddr_in?

一個例子是:我們有一個套接字,我們想得到它的字符串IP地址(它可以是ipv4或ipv6)。

我們首先調用getsockname得到一個addr ,然后調用inet_ntop基礎上, addr.sa_family

這段代碼片段有什么問題嗎?

char ipStr[256];
sockaddr_in6 addr_inv6;
sockaddr* addr = (sockaddr*)&addr_inv6;
sockaddr_in* addr_in = (sockaddr_in*)&addr_inv6;

socklen_t len = sizeof(addr_inv6);
getsockname(_socket, addr, &len);

if (addr->sa_family == AF_INET6) {
    inet_ntop(addr_inv6.sin6_family, &addr_inv6.sin6_addr, ipStr, sizeof(ipStr)); 
    // <<<<<<<<IS THIS LINE VALID, getsockname expected a sockaddr, but we use 
    // it output parameter as sockaddr_in6.
} else {
    inet_ntop(addr_in->sin_family, &addr_in->sin_addr, ipStr, sizeof(ipStr));
}

sockaddr_insockaddr_in6都是第一個成員是sockaddr結構的結構。

根據C標准,一個結構的地址和它的第一構件是相同的,這樣就可以轉換指針到sockaddr_in(6)中的指針sockaddr

sockaddr_in(6)作為參數的函數可以修改sockaddr部分,並且將sockaddr作為參數的函數只關心該部分。

這有點像繼承。

我不想回答我的問題。 但是為了提供更多可能對其他人有用的信息,我決定回答我的問題。

深入挖掘linux的源代碼。 以下是我的發現,可能有多個協議都實現了getsockname 而且每個都有下屬自理地址數據結構,例如,對IPv4是sockaddr_in ,而IPV6 sockaddr_in6 ,並sockaddr_unAF_UNIX插座。 sockaddr用作這些API簽名中的公共數據支柱。

這些API會將memadpy的socketaddr_in或sockaddr_in6或sockaddr_un復制到另一個參數length的sockaddr。

並且所有數據結構都以相同的類型字段sa_family開頭。

基於這些原因,代碼片段是有效的,因為sockaddr_insockaddr_in6都有sa_family ,然后我們可以在檢查sa_family之后將其轉換為正確的數據結構以供使用。

BTY,我不知道為什么sizeof(sockaddr_in6) > sizeof(sockaddr)導致基於sockaddr大小的內存分配對於ipv6來說還不夠(這很容易出錯),但我想這是因為歷史原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM