【发布时间】:2011-05-26 16:59:15
【问题描述】:
在我的 C++ 应用程序中,我使用 sockaddr。我想查看 sockaddr.sa_data[14] 拥有的所有信息。现在我只打印来自 sa_data[2].sa_data[3].sa_data[4].sa_data[5] 的 ip。
我想以我能理解(并请解释)sa_data 14 字节中的所有信息的方式打印。
有什么帮助吗?
谢谢!
【问题讨论】:
在我的 C++ 应用程序中,我使用 sockaddr。我想查看 sockaddr.sa_data[14] 拥有的所有信息。现在我只打印来自 sa_data[2].sa_data[3].sa_data[4].sa_data[5] 的 ip。
我想以我能理解(并请解释)sa_data 14 字节中的所有信息的方式打印。
有什么帮助吗?
谢谢!
【问题讨论】:
要获取和打印struct sockaddr 的sa_data member,请参考约翰在Getting IPV4 address from a sockaddr structure 的回答
【讨论】:
14 字节的 sa_data 的值根据地址族 sa_family 改变(不同)。
如果地址族是 AF_INET,前两个字节是端口号,接下来的 4 个字节是源 IP 地址。
如果地址族是PF_PACKET,前两个字节告诉以太网类型(wither 0800--> IP, 0806 --> ARP etc..),接下来的 4 个字节(实际上第一个就足够了)它告诉源接口。如果值为:
【讨论】:
在 sa_data 成员中,对于 Windows 上的 IPv4,我发现前两个字节保存端口号,接下来的四个字节保存 IP 地址。
比如我解析地址228.0.0.1:9995,sa_data成员就是……
27 0b e4 00 00 01 00 00 00 00 00 00 00 00
这里,270b 是前两个字节中 9995 的十六进制值表示。接下来的四个字节是 IP 地址,其中0xe4 是 228,然后是两个零,然后是 0x01,或 228 0 0 1。
最后 8 个字节未使用,这与上面关于仅使用前 6 个字节的评论一致。
请注意,sa_data 的格式会因所使用的协议而异。
【讨论】:
一种可能性是使用inet_ntop,它应该能够处理 IPv4 和 IPv6 地址。它将生成一个带有地址的人类可读字符串。
【讨论】:
sockaddr 中的信息取决于您使用的套接字系列和协议。
如果您使用的是 IPv4,正确的做法是将 sockaddr 指针转换为 sockaddr_in *。使用 IPv4 时,只有地址的前 6 个字节有意义。其余的应该被忽略。
【讨论】:
std::copy( &sa_data[0], &sa_data[0]+sizeof(sa_data)/sizeof(sa_data[0]),
std::ostream_iterator<int>(std::cout, " "));
将每个元素打印为一个以空格分隔的 int。如果您不想要负值,也可以使用 unsigned int,如果您愿意,也可以通过 iomanip 流来打印十六进制。
【讨论】: