C++ sockaddr、sockaddr_in 和 sockaddr_in6 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18609397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?
提问by ZijingWu
I know that sockaddr_in is for IPv4, and sockaddr_in6 for IPv6. The confusion to me is the difference between sockaddr and sockaddr_in[6].
我知道 sockaddr_in 用于 IPv4,而 sockaddr_in6 用于 IPv6。令我困惑的是 sockaddr 和 sockaddr_in[6] 之间的区别。
Some functions accept sockaddr
and some functions accept sockaddr_in
or sockaddr_in6
, so:
有些函数接受sockaddr
,有些函数接受sockaddr_in
or sockaddr_in6
,所以:
- what's the rule?
- And why is there a need for two different structures?
- 规则是什么?
- 为什么需要两种不同的结构?
And because the sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)
.
并且因为sizeof(sockaddr_in6) > sizeof(sockaddr) == sizeof(sockaddr_in)
.
- Does that mean we should always use sockaddr_in6 to allocate memory in stack and cast to sockaddr and sockaddr_in if we need to support ipv4 and ipv6?
- 这是否意味着如果我们需要支持 ipv4 和 ipv6,我们应该总是使用 sockaddr_in6 在堆栈中分配内存并强制转换为 sockaddr 和 sockaddr_in ?
One example is: we have a socket, and we want to get the string ip address of it (it can be ipv4 or ipv6).
一个例子是:我们有一个socket,我们想获取它的字符串ip地址(可以是ipv4或ipv6)。
We first call getsockname
to get an addr
and then call inet_ntop
based on the addr.sa_family
.
我们首先调用getsockname
get anaddr
然后inet_ntop
根据调用addr.sa_family
。
Is there anything wrong with this code snippet?
这个代码片段有什么问题吗?
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));
}
采纳答案by ZijingWu
I don't want to answer my question. But to give more information here which might be useful to other people, I decide to answer my question.
我不想回答我的问题。但是为了在此处提供可能对其他人有用的更多信息,我决定回答我的问题。
After dig into the source code of linux
. Following is my finding, there are possible multiple protocol which all implement the getsockname
. And each have themself underling address data structure, for example, for IPv4 it is sockaddr_in
, and IPV6 sockaddr_in6
, and sockaddr_un
for AF_UNIX
socket. sockaddr
are used as the common data strut in the signature of those APIs.
在深入研究linux
. 以下是我的发现,可能有多种协议都实现了getsockname
. 并且每个都有自己的底层地址数据结构,例如,对于IPv4,它是sockaddr_in
,和IPV6 sockaddr_in6
,sockaddr_un
对于AF_UNIX
套接字。sockaddr
在这些 API 的签名中用作公共数据支柱。
Those API will copy the socketaddr_in or sockaddr_in6 or sockaddr_un to sockaddr base on another parameter length
by memcpy.
这些 API 将length
根据 memcpy 的另一个参数将 socketaddr_in 或 sockaddr_in6 或 sockaddr_un 复制到 sockaddr 。
And all of the data structure begin with same type field sa_family.
并且所有数据结构都以相同类型的字段 sa_family 开头。
Base on those reason, the code snippet is valid, because both sockaddr_in
and sockaddr_in6
have sa_family
and then we can cast it to the correct data structure for usage after check sa_family
.
底座上的原因,该代码段是有效的,因为两者sockaddr_in
并sockaddr_in6
有sa_family
然后我们就可以检查后转换为正确的数据结构使用sa_family
。
BTY, I'm not sure why the sizeof(sockaddr_in6) > sizeof(sockaddr)
, which cause allocate memory base on size of sockaddr is not enough for ipv6( that is error-prone), but I guess it is because of history reason.
BTY,我不确定为什么sizeof(sockaddr_in6) > sizeof(sockaddr)
根据 sockaddr 的大小分配内存的 , 对 ipv6 来说是不够的(容易出错),但我想这是因为历史原因。
回答by linkdd
sockaddr_in
and sockaddr_in6
are both structures where first member is a sockaddr
structure.
sockaddr_in
和sockaddr_in6
都是结构,其中第一个成员是sockaddr
结构。
According to the C standard, the address of a structure and its first member are the same, so you can cast the pointer to sockaddr_in(6)
in a pointer to sockaddr
.
根据 C 标准,结构的地址与其第一个成员的地址相同,因此您可以将指针转换sockaddr_in(6)
为指向 的指针sockaddr
。
Functions taking sockaddr_in(6)
as parameter may modify the sockaddr
part, and functions taking sockaddr
as parameter just care about that part.
以功能sockaddr_in(6)
为参数可修改sockaddr
的部分,并采取功能sockaddr
作为参数只关心那部分。
It's a bit like inheritance.
有点像继承。