2015-01-06 2 views
3

Мне нужно преобразовать адрес сокета, который размещается в структуре sockaddr для структуры in_addr. Я пытался понять, как IP хранится в этих структурах:Преобразовать IP-адрес от sockaddr в in_addr

struct sockaddr { 
     u_short sa_family;    /* address family */ 
     char sa_data[14];   /* up to 14 bytes of direct address */ 
}; 


struct in_addr { 
     union { 
       struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; 
       struct { u_short s_w1,s_w2; } S_un_w; 
       u_long S_addr; 
     } S_un; 

я застрял с вопросом, как 127.0.0.1 хранится в 14 символов sa_data. Каков наилучший способ конвертировать sockaddr в in_addr?

+0

Этот вопрос говорит о кодировке - https://stackoverflow.com/questions/1276294/getting-ipv4-address-from-a-sockaddr-structure – sashoalm

ответ

5

sockaddr - это общая структура, которая разделяется различными типами сокетов. Для сокетов TCP/IP эта структура становится sockaddr_in. Для разъемов unix он становится sockaddr_un.

В идеале вы бы использовали sockaddr_in вместо sockaddr.

Но учитывая sockaddr, чтобы извлечь IP-адрес из него вы могли бы сделать это:

sockaddr foo; 
in_addr ip_address = ((sockaddr_in)foo).sin_addr; 
or 
in_addr_t ip_address = ((sockaddr_in)foo).sin_addr.s_addr; 

Если вы посмотрите внутрь sockaddr_in вы увидите, что первые 2 байта sa_data являются номер порта. А следующие 4 байта - это IP-адрес.

PS: Обратите внимание, что IP-адрес хранится в сетевом порядке, поэтому вам, возможно, потребуется использовать ntohl (network-to-host) и htonl (хост-сеть) для преобразования в/из хоста заказ.

UPDATE

Для IPv6 вещи похожи:

sockaddr foo; 
in_addr6 ip_address = ((sockaddr_in6)foo).sin6_addr; 

Чтобы получить доступ к отдельным байт, используйте ip_address[0] ... ip_address[15].

Внутри struct первые 2 байта sa_data являются номером порта, следующие 4 байта являются информацией о потоке, и после этого следующие 16 байтов являются IPv6-адресом.

остерегается, однако, что является больше чем sockaddr, поэтому при литье из sockaddr в , убедитесь, что адрес действительно адрес IPv6 путем проверки адреса семьи foo.sa_family == AF_INET6.

+0

Это то, что мне нужно. Но как конвертировать, когда у меня есть IPV6? – vico

+0

@ vico, я обновил ответ. Возможно, вы также должны обновить вопрос, поскольку в нем не упоминалось IPv6. Если вы довольны ответом, не стесняйтесь принять его. –

Смежные вопросы