[英]What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?
我知道sockaddr_in用於IPv4,sockaddr_in6用於IPv6。 我的困惑是sockaddr和sockaddr_in之間的區別[6]。
有些函數接受sockaddr
,有些函數接受sockaddr_in
或sockaddr_in6
,所以:
並且因為sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(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_in
和sockaddr_in6
都是第一個成員是sockaddr
結構的結構。
根據C標准,一個結構的地址和它的第一構件是相同的,這樣就可以轉換指針到sockaddr_in(6)
中的指針sockaddr
。
以sockaddr_in(6)
作為參數的函數可以修改sockaddr
部分,並且將sockaddr
作為參數的函數只關心該部分。
這有點像繼承。
我不想回答我的問題。 但是為了提供更多可能對其他人有用的信息,我決定回答我的問題。
深入挖掘linux
的源代碼。 以下是我的發現,可能有多個協議都實現了getsockname
。 而且每個都有下屬自理地址數據結構,例如,對IPv4是sockaddr_in
,而IPV6 sockaddr_in6
,並sockaddr_un
為AF_UNIX
插座。 sockaddr
用作這些API簽名中的公共數據支柱。
這些API會將memadpy的socketaddr_in或sockaddr_in6或sockaddr_un復制到另一個參數length
的sockaddr。
並且所有數據結構都以相同的類型字段sa_family開頭。
基於這些原因,代碼片段是有效的,因為sockaddr_in
和sockaddr_in6
都有sa_family
,然后我們可以在檢查sa_family
之后將其轉換為正確的數據結構以供使用。
BTY,我不知道為什么sizeof(sockaddr_in6) > sizeof(sockaddr)
導致基於sockaddr大小的內存分配對於ipv6來說還不夠(這很容易出錯),但我想這是因為歷史原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.