在我的Linux C ++应用程序中,我使用的是getpeername和getsockname。 在操作系统上启用IPv6时,getpeername和getsockname都只返回端口!
代码:
int GetSockAndPeer(int sock)
{
struct sockaddr_storage ss;
socklen_t salen = sizeof(ss);
struct sockaddr *sa;
struct addrinfo hints, *paddr, *paddrp;
sa = (struct sockaddr *)&ss;
if (getpeername(sock, sa, &salen) != 0)
{
return -1;
}
if (getsockname(sock, sa, &salen) != 0)
{
return -1;
}
}
在sa_data中系统调用sa_data [0]和sa_data [1](表示端口)之后的变量保持。所有其他字节都是0;
任何帮助???
答案 0 :(得分:1)
与RFC2553相关,您必须使用IN6_IS_ADDR_V4MAPPED
和IN6_IS_ADDR_V4COMPAT
宏来确定您的socket_storage
内是否有可用的IPv4信息,或者确切地说是sockaddr_in6
结构:
struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* set of interfaces for a scope */
};
如果两个宏都返回true
,则IPv4地址位于sockaddr_in6.sin6_addr[12-15]
:
printf("%u.%u.%u.%u\n", sockaddr_in6.sin6_addr[12], sockaddr_in6.sin6_addr[13], \
sockaddr_in6.sin6_addr[14], sockaddr_in6.sin6_addr[15])
答案 1 :(得分:0)
重要的是要记住,除非连接套接字(或者,对于无连接套接字,已传输数据),可能没有任何与套接字关联的本地或远程IP地址。
假设计算机是多宿主的,并且具有本地和Internet IP地址。甚至可能是多个本地网络IP地址。如果您选择将套接字绑定到“任何”本地地址(使用INADDR_ANY类型标志),或者从不首先调用bind(),则套接字API没有与套接字关联的单个本地IP地址,只是最多的端口号。当您在套接字上调用connect()时,系统会根据您要连接的人选择要使用的本地IP。因此,如果通过Internet连接到计算机,则Internet IP与套接字关联,如果连接到本地网络上的计算机,则使用LAN IP地址。
因此,在使用getsockname()之前,可以确保将connect()连接到远程计算机或bind()到特定的本地IP。我想知道启用IPv6是否会导致您的计算机看到多个可能使用的本地IP。显然你很多都被连接到机器上以使用getpeername()。