C ++ Linux getpeername и getsockname возвращают только порт - PullRequest
0 голосов
/ 09 января 2011

В моем приложении на 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 удерживается после того, как системные вызовы в sa_data только для sa_data [0] и sa_data [1] что означает порт.все остальные байты равны 0;

Любая помощь ???

Ответы [ 2 ]

1 голос
/ 09 января 2011

Относительно RFC2553 вы должны использовать макросы IN6_IS_ADDR_V4MAPPED и IN6_IS_ADDR_V4COMPAT, чтобы определить, есть ли какая-либо полезная информация IPv4, доступная в вашем socket_storage, или, точнее, структура 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])
0 голосов
/ 12 января 2012

Важно помнить, что, если сокет не подключен (или для сокета без установления соединения не передал данные), с этим сокетом может не быть никаких локальных или удаленных IP-адресов.

Допустим, компьютер является многосетевым и имеет как локальные, так и интернет-IP-адреса. Может быть, даже несколько IP-адресов локальной сети. Если вы решите связать сокет с «любым» локальным адресом (используя флаг типа INADDR_ANY) или никогда не вызывать bind (), то у API сокета нет ни одного локального IP-адреса, связанного с сокетом, просто Максимальный номер порта. Когда вы вызываете connect () для сокета, система выбирает, какой локальный IP-адрес использовать, в зависимости от того, к кому вы подключаетесь. Поэтому, если вы подключаетесь к машине через Интернет, ваш IP-адрес в Интернете связан с сокетом, а если вы подключаетесь к машине в локальной сети, используется ваш IP-адрес в локальной сети.

Поэтому вы можете быть уверены, что подключили () к удаленному компьютеру или привязали () к определенному локальному IP-адресу, прежде чем использовать getsockname (). Интересно, вызвало ли включение IPv6 вашу машину, чтобы увидеть несколько потенциальных локальных IP-адресов для использования. Очевидно, что вы сильно подключены к машине, чтобы использовать getpeername ().

...