2012-07-27 13 views
9

Estoy tratando de obtener la dirección del cliente, pero no estoy seguro de cómo se puede convertir la estructura sockaddr a sockaddr_in?cómo se hace la estructura sockaddr a sockaddr_in - sockets de red C++ ubuntu UDP

struct sockaddr_in cliAddr, servAddr; 

    n = recvfrom(sd, msg, MAX_MSG, 0,(struct sockaddr *) cliAddr,sizeof(cliAddr)); 

//i tried this but it does not work 
    struct sockaddr cliSockAddr = (struct sockaddr *) cliAddr; 
    char *ip = inet_ntoa(cliSockAddr.sin_addr); 

¡Gracias de antemano! :)


he encontrado preguntas que me trajeron a este paso: Getting IPV4 address from a sockaddr structure


En este momento, para evitar confusiones, esta es mi verdadera aplicación donde "ci" es un objeto para almacenar punteros como sockaddr_in.

/* receive message */ 
    n = recvfrom(*(ci->getSd()), msg, MAX_MSG, 0,(struct sockaddr *) ci->getCliAddr(),ci->getCliLen()); 

    char *ip = inet_ntoa(ci->getCliAddr().sin_addr); 

voy a tener los siguientes errores:

udpserv.cpp:166: error: request for member ‘sin_addr’ in ‘ci->clientInfo::getCliAddr()’, which is of non-class type ‘sockaddr_in*’ 
+0

Tu código ni siquiera compilará. Está asignando un puntero a una estructura, declara 'cliSockAddr' como un puntero. –

+0

Lo que realmente está preguntando es el reverso de lo que dice en su título. – EJP

Respuesta

13

En realidad, es muy simple!

struct sockaddr *sa = ...; 

if (sa->sa_family == AF_INET) 
{ 
    struct sockaddr_in *sin = (struct sockaddr_in *) sa; 
    ip = inet_ntoa(sin->sin_addr); 
} 
+0

muchas gracias! : D – mister

+3

Y mientras lo hace, habilite el programa IPv6 también para AF_INET6. ;) – onitake

2

Creo que compilará muy bien para usted y hará lo que quiera.

struct sockaddr_in cliAddr={}, servAddr={}; 

socklen_t cliAddrLength = sizeof(cliAddr); 

n = recvfrom(sd, msg, MAX_MSG, 0,(struct sockaddr *)&cliAddr, &cliAddrLength); 
18

me gustaría señalar que si esto es en realidad C++ la forma idiomática para hacer esto sería:

código
sockaddr *sa = ...; // struct not needed in C++ 
char ip[INET6_ADDRSTRLEN] = {0}; 

switch (sa->sa_family) { 
    case AF_INET: { 
    // use of reinterpret_cast preferred to C style cast 
    sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sa); 
    inet_ntop(AF_INET, &sin->sin_addr, ip, INET6_ADDRSTRLEN); 
    break; 
    } 
    case AF_INET6: { 
    sockaddr_in6 *sin = reinterpret_cast<sockaddr_in6*>(sa); 
    // inet_ntoa should be considered deprecated 
    inet_ntop(AF_INET6, &sin->sin6_addr, ip, INET6_ADDRSTRLEN); 
    break; 
    } 
    default: 
    abort(); 
} 

Esta muestra se ocupa de las direcciones IPv4 e IPv6 y también sería considerado más C++ idiomática de cualquiera de las implementaciones sugeridas.

+0

Me gusta mucho que hayas usado reinterpret_cast. Hace que todo sea mucho más limpio, y se necesitan menos punteros. En una nota lateral, no establecí sa como un puntero para empezar. Simplemente le pasé la dirección a través de una referencia de este modo (el mío es un proyecto escolar y solo usa IPv4 - inet_ntoa (reinterpret_cast (& clientIpAddress) -> sin_addr) – adpro

Cuestiones relacionadas