什么是套接字地址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_IN
或体sockaddr_in6
,所以:
- 有什么规则?
- 为什么有需要两种不同的结构?
和因为的sizeof(体sockaddr_in6)GT;的sizeof(SOCKADDR)==的sizeof(SOCKADDR_IN)
。
- 这是否意味着我们应该经常使用到sockaddr_in6的堆栈中分配内存和强制转换为sockaddr并有sockaddr_in如果我们需要支持IPv4和IPv6?
一个例子是:我们有一个插座上,我们希望得到它的字符串的IP地址(可以是IPv4或IPv6)
。我们第一次调用 getsockname
来获得地址
,然后调用 inet_ntop
根据 addr.sa_family
。
这有什么不对的code段?
体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,地址,和放大器; LEN);
焦炭ipStr [256];
如果(addr->上sa_family == AF_INET6)
{
inet_ntop(addr_inv6.sin6_family,&安培; addr_inv6.sin6_addr,ipStr,sizeof的(ipStr));
//<<<<<<<<这是线路有效,getsockname预期sockaddr的,但我们把它输出参数为体sockaddr_in6。
}
其他
{
inet_ntop(addr_in-> sin_family,&安培; addr_in-> sin_addr,属于ipStr,sizeof的(ipStr));
}
我不想回答我的问题。但是,给这里的更多信息,我决定回答我的问题可能是别人有用的。
钻进去的Linux源$ C $ C后
。以下是我的发现,还有一些都实现了 getsockname
可能的多个协议。而且每个人都有自理下属地址数据结构,例如,对于IPv4是 SOCKADDR_IN
和IPV6 体sockaddr_in6
和 sockaddr_un
为 AF_UNIX
插座。 的sockaddr
被用作这些API的签名常见的数据支撑。
这些API将复制socketaddr_in或或sockaddr_in6的到sockaddr_un另一个参数长度
则memcpy指向sockaddr基地。
和所有的数据结构的开始与上sa_family相同类型字段
基础对原因,code段是有效的,因为这两个 SOCKADDR_IN
和体sockaddr_in6
有上sa_family
然后我们就可以检查后,将它转换为正确的数据结构使用上sa_family
。
BTY,我不知道为什么的sizeof(体sockaddr_in6)GT;的sizeof(SOCKADDR)
,它造成的sockaddr的大小分配内存的基础是不够的,IPv6的(即容易出错),但我想这是因为历史原因。
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].
Some functions accept sockaddr
and some functions accept sockaddr_in
or sockaddr_in6
, so:
- 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)
.
- 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?
One example is: we have a socket, and we want to get the string ip address of it (it can be ipv4 or ipv6).
We first call getsockname
to get an addr
and then call inet_ntop
based on the addr.sa_family
.
Is there anything wrong with this code snippet?
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);
char ipStr[256];
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));
}
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.
Those API will copy the socketaddr_in or sockaddr_in6 or sockaddr_un to sockaddr base on another parameter length
by memcpy.
And all of the data structure begin with same type field 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
.
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.
这篇关于什么是套接字地址SOCKADDR_IN和sockaddr_in6的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!