2011-01-09 121 views
0

在我的Linux C++应用程序中,我使用getpeername和getsockname。当在操作系统上启用IPv6时,getpeername和getsockname只返回端口!C++ Linux getpeername和getsockname仅返回端口

代码:仅sa_data [0]和sa_data [1]这意味着端口sa_data的systemcalls后

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变量保持。所有其他字节都是0;

任何帮助?

+0

与大多数问题相关,__RFC2553:IPv6__基本套接字接口扩展(http://www.faqs.org/rfcs/rfc2553.html)将是一个很好的解读。否则,请使用支持IPv4/IPv6的boost.ASIO(http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio.html)库。 – 2011-01-09 15:04:04

+0

该代码不应该如果启用了足够的编译器警告/错误,则进行编译:如果未采用条件,则它不会返回任何值。 至于帮助我们帮助你,对你想要做什么的一些解释是有用的。 – 2011-01-09 15:15:15

回答

1

相关的RFC2553您必须使用IN6_IS_ADDR_V4MAPPEDIN6_IS_ADDR_V4COMPAT宏,以确定是否有可用之内你socket_storage任何可用的IPv4信息,或者确切的结构:

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]) 
0

请务必记住,除非一个套接字已连接(或者,对于无连接套接字,已传输数据),则可能没有任何与套接字关联的本地或远程IP地址。

假设计算机是多宿主机,并且同时拥有本地和Internet IP地址。甚至可能有多个本地网络IP地址。如果您选择将套接字绑定到“任何”本地地址(使用INADDR_ANY类型标志),或者从不首先调用bind(),则套接字API没有与套接字关联的单个本地IP地址,只是最多的端口号。当您在套接字上调用connect()时,系统将根据您连接的人选择使用哪个本地IP。因此,如果您通过Internet连接到计算机,则您的Internet IP与套接字关联,并且如果连接到本地网络上的计算机,则会使用您的LAN IP地址。

因此,在使用getsockname()之前,可以确保连接()到远程计算机或将bind()绑定到特定的本地IP。我想知道是否启用IPv6导致您的机器看到多个潜在的本地IP使用。很显然,你很多连接到一台机器使用getpeername()。