我正在尝试基于此处给出的教程在C ++中创建基本的Web服务器:
https://vichargrave.github.io/articles/2013-02/tcp-ip-network-programming-design-patterns-in-cpp
我无法理解以下内容:
inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1);
具体来说,我无法理解第二个参数:
(struct in_addr*)&(address->sin_addr.s_addr)
正在做。这个参数是我以前没有见过的语法,基于我所知道它正在做两件事之一:
它是一个结构in_addr
指针与地址或
它将address->sin_addr.s_addr
的地址转换为指针struct in_addr*
是哪一个?
编辑:
所以它似乎是演员。这引出了另一个问题。该参数似乎是将类型in_addr_t
的变量强制转换为一个没有意义的结构。这是对它的正确看法还是做其他事情?
此外,我正在引用以下页面以获取有关此功能的文档:
http://pubs.opengroup.org/onlinepubs/7908799/xns/netinetin.h.html http://pubs.opengroup.org/onlinepubs/009695399/functions/inet_ntop.html
答案 0 :(得分:1)
为了更好地理解,请从右到左阅读。
(struct in_addr*)&(address->sin_addr.s_addr)
所以,
address->sin_addr.s_addr --> uses the "address" ptr to access sin_addr.s_addr
然后
&(address->sin_addr.s_addr) takes the address of s_addr.
然后
(struct in_addr*) casts the address taken by & to in_addr.
以上是有道理的,因为在这种情况下,以下2是等效的
(struct in_addr*)&(address->sin_addr.s_addr)
(struct in_addr*)&(address->sin_addr)
结构的地址与C / C ++中第一个成员的地址相同。
答案 1 :(得分:1)
要回答您的第一个问题,它确实将address->sin_addr.s_addr
字段的地址转换为struct in_addr*
指针。由于问题标记为c++
,因此C ++样式转换会更清晰:
inet_ntop(PF_INET, reinterpret_cast<struct in_addr*>(&(address->sin_addr.s_addr)), ip, sizeof(ip)-1);
要回答第二个问题,它不会将变量本身转换为指针。它将变量的地址转换为不同的指针类型。在这种情况下,s_addr
字段的地址将转换为struct in_addr*
指针。类型的第一个字段的地址与类型本身的地址相同。因此,将s_addr
的地址转换为struct in_addr*
在技术上是安全的。
然而,话虽如此,演员阵容是多余的,应该被删除。 inet_ntop()
的第二个参数是const void*
,任何指针都可以as_is指定给void*
。当第一个参数为(AF|PF)_INET
时,第二个参数必须是指向struct in_addr
的指针,因此您应该使用sin_addr
字段本身的地址(这是一个实际in_addr
}),而不是s_addr
字段(in_addr
内的字段):
inet_ntop(AF_INET, &(address->sin_addr), ip, sizeof(ip)-1);
如果您有IPv6地址(第一个参数是(AF|PF)_INET6
),则第二个参数必须是指向struct in6_addr
的指针,该sin6_addr
字段是sockaddr_in6
的{{1}}字段。 1}}:
inet_ntop(AF_INET6, &(address->sin6_addr), ip, sizeof(ip)-1);
为了支持两个家庭(首先使用inet_ntop()
的主要原因),address
应该是指向struct sockaddr_storage
的指针(大到足以容纳任何一个) struct sockaddr_...
类型,但在这种情况下为IPv4和IPv6地址),ip
需要至少46个字符(最好使用INET6_ADDRSTRLEN
定义)。然后,您可以执行以下操作:
switch (address->ss_family)
{
case AF_INET:
inet_ntop(AF_INET, &(reinterpret_cast<struct sockaddr_in*>(address)->sin_addr), ip, sizeof(ip)-1);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(reinterpret_cast<struct sockaddr_in6*>(address)->sin6_addr), ip, sizeof(ip)-1);
break;
}