¿Cómo puedo extraer una dirección IP en una cadena? No puedo encontrar una referencia que me diga cómo char sa_data[14]
está codificado.
Obtener la dirección IPV4 de una estructura sockaddr
Felipe Salazar
Solo lanza todo sockaddr
estructura a un calcetínaddr_in. Entonces puedes usar:
char *ip = inet_ntoa(their_addr.sin_addr)
Para recuperar la representación de ip estándar.
-
+1. Según la plataforma, recuerda comprobar primero la familia. Puede que no haya una dirección IPV4 para extraer…
–Steve Jessop
14 de agosto de 2009 a las 10:40
-
@SteveJessop ¿Cómo hacemos la verificación por cierto? ¿Hay algún código de ejemplo o algo que buscar?
– Fatih Arslan
13 de julio de 2012 a las 13:42
-
if (their_sockaddr_ptr->sa_family == AF_INET) { struct sockaddr_in *their_inaddr_ptr = (struct sockaddr_in *)their_sockaddr_ptr; } else { /* not an IPv4 address */ }
o similar.–Steve Jessop
13 de julio de 2012 a las 14:32
-
@Emil ¿Cómo conviertes toda la estructura sockaddr en sockaddr_in? Capaz de dar un ejemplo? 😀
– señor
27 de julio de 2012 a las 8:11
-
@mister Si tiene una pregunta, comience la pregunta, para eso está SO aquí. Las preguntas son ciudadanos de primera clase en SO. Y la respuesta es, ¡simplemente lánzalo!
sockaddr
es solo una dirección “abstracta”, ninguna dirección es realmente de ese tipo, solo define los campos comunes que deben tener todas las estructuras socketaddr.struct sockaddr * saddr = ...; if (saddr->sa_family == AF_INET) { struct sockaddr_in * saddr_in = (sockaddr_in *)saddr; ... }
– Mecki
10 de agosto de 2016 a las 10:35
jrc
inet_ntoa()
funciona para IPv4; inet_ntop()
funciona tanto para IPv4 como para IPv6.
Dada una entrada struct sockaddr *res
aquí hay dos fragmentos de código (probados en macOS):
Usando inet_ntoa()
#include <arpa/inet.h>
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
char *s = inet_ntoa(addr_in->sin_addr);
printf("IP address: %s\n", s);
Usando inet_ntop()
#include <arpa/inet.h>
#include <stdlib.h>
// obviously INET6_ADDRSTRLEN is expected to be larger
// than INET_ADDRSTRLEN, but this may be required in case
// if for some unexpected reason IPv6 is not supported, and
// INET6_ADDRSTRLEN is defined as 0
// but this is not very likely and I am aware of no cases of
// this in practice (editor)
char s[INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN]
= '\0';
switch(res->sa_family) {
case AF_INET: {
struct sockaddr_in *addr_in = (struct sockaddr_in *)res;
////char s[INET_ADDRSTRLEN] = '\0';
// this is large enough to include terminating null
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)res;
////char s[INET6_ADDRSTRLEN] = '\0';
// not sure if large enough to include terminating null?
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
break;
}
default:
break;
}
printf("IP address: %s\n", s);
-
en que encabezado
– usuario1462586
12 de junio de 2020 a las 7:02
-
#incluye
– jrc
18 de junio de 2020 a las 21:42
-
No estoy seguro de por qué está usando malloc y gratis aquí, un búfer estático sería la solución más apropiada.
– Consultor independiente
15 de mayo de 2021 a las 14:22
Juan
La respuesta de Emil es correcta, pero tengo entendido que inet_ntoa
está en desuso y que en su lugar deberías usar inet_ntop
. Si está utilizando IPv4, emita su struct sockaddr
para sockaddr_in
. Su código se verá algo como esto:
struct addrinfo *res; // populated elsewhere in your code
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
char ipAddress[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(ipv4->sin_addr), ipAddress, INET_ADDRSTRLEN);
printf("The IP address is: %s\n", ipAddress);
Echa un vistazo a este gran recurso para obtener más explicaciones, incluido cómo hacer esto para las direcciones IPv6.
Ámbar
Una vez sockaddr
lanzar a sockaddr_in
se convierte en esto:
struct sockaddr_in {
u_short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
Puedes usar getnameinfo
para ventanas y para Linux.
Suponiendo que tiene un bien (es decir, sus miembros tienen valores apropiados) sockaddr*
llamado pSockaddr
:
char clienthost[NI_MAXHOST]; //The clienthost will hold the IP address.
char clientservice[NI_MAXSERV];
int theErrorCode = getnameinfo(pSockaddr, sizeof(*pSockaddr), clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV);
if( theErrorCode != 0 )
{
//There was an error.
cout << gai_strerror(e1) << endl;
}else{
//Print the info.
cout << "The ip address is = " << clienthost << endl;
cout << "The clientservice = " << clientservice << endl;
}
x-yuri
El siguiente programa resuelve un dominio dado:
$ gcc a.c
$ ./a.out google.com
AF_INET: 216.58.214.238
AF_INET6: 2a00:1450:400d:803::200e
$ ./a.out google.com af_inet
AF_INET: 216.58.214.238
a.c
:
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
int
main(int argc, char *argv[])
{
struct addrinfo hints, *res, *cres;
int r;
char s[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof(hints));
if (argc > 2)
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
r = getaddrinfo(argv[1], NULL, &hints, &res);
if (r) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(r));
exit(EXIT_FAILURE);
}
for (cres = res; cres; cres = cres->ai_next) {
switch (cres->ai_family) {
case AF_INET:
inet_ntop(AF_INET, &((struct sockaddr_in *)cres->ai_addr)->sin_addr, s, INET6_ADDRSTRLEN);
printf("AF_INET: %s\n", s);
break;
case AF_INET6:
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)cres->ai_addr)->sin6_addr, s, INET6_ADDRSTRLEN);
printf("AF_INET6: %s\n", s);
break;
}
}
freeaddrinfo(res);
}
Otro ejemplo se puede encontrar aquí.
Aamir
Tipo de fundición de sockaddr
para sockaddr_in
y recuperación de ipv4 usando inet_ntoa
char * ip = inet_ntoa(((struct sockaddr_in *)sockaddr)->sin_addr);