2010-01-14 17 views
16

Tengo un servidor con un socket entrante de un cliente. Necesito obtener la dirección IP del cliente remoto. Intentado buscar en google por in_addr pero es un poco molesto. ¿Alguna sugerencia?Obtener la dirección de origen de una conexión de socket entrante

+0

in_addr es IPv4 específica, de todos modos – bortzmeyer

+0

ver la función inet_ntoa (..) en linux .. 'hombre inet_ntoa'. es más fácil que inet_ntop en mi opinión y necesidades, incluyendo arpa/inet.h. aquí hay un ejemplo: http://www.binarytides.com/programming-udp-sockets-c-linux/ – mhk

Respuesta

32

Necesita la función getpeername. La gran guía de Beej para redes tiene un page about it. Aquí está un ejemplo de código de allí:

// assume s is a connected socket 

socklen_t len; 
struct sockaddr_storage addr; 
char ipstr[INET6_ADDRSTRLEN]; 
int port; 

len = sizeof addr; 
getpeername(s, (struct sockaddr*)&addr, &len); 

// deal with both IPv4 and IPv6: 
if (addr.ss_family == AF_INET) { 
    struct sockaddr_in *s = (struct sockaddr_in *)&addr; 
    port = ntohs(s->sin_port); 
    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); 
} else { // AF_INET6 
    struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; 
    port = ntohs(s->sin6_port); 
    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); 
} 

printf("Peer IP address: %s\n", ipstr); 
+0

+1. Sin embargo, ¿no tenemos que liberar memoria para esto? – iammilind

+1

Noto que 'struct sockaddr_in * s' sombrea el socket' s' en el ámbito externo. Tener una variable sombreada no es ideal. –

+0

hay una manera de obtener el socketDescriptor desde la dirección – Bionix1441

1

Dado que usted dice que es una conexión entrante de un cliente, como una alternativa a getpeername sólo puede guardar la dirección que fue devuelto por la llamada accept(), en el segundo y tercer parámetros.

9

Suponiendo que está utilizando accept() para aceptar conexiones de socket entrantes, getpeername() no es necesario. La información de la dirección está disponible a través de los parámetros 2 y 3 de la llamada accept().

Aquí está la respuesta de Eli modificado para hacerlo sin getpeername():

int client_socket_fd; 
socklen_t len; 
struct sockaddr_storage addr; 
char ipstr[INET6_ADDRSTRLEN]; 
int port; 

len = sizeof addr; 
client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len); 

// deal with both IPv4 and IPv6: 
if (addr.ss_family == AF_INET) { 
    struct sockaddr_in *s = (struct sockaddr_in *)&addr; 
    port = ntohs(s->sin_port); 
    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); 
} else { // AF_INET6 
    struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; 
    port = ntohs(s->sin6_port); 
    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); 
} 

printf("Peer IP address: %s\n", ipstr); 
+0

+1 para usar directamente 'accept() '. Sin embargo, ¿no tenemos que liberar memoria para esto? – iammilind

+3

@iammilind: No creo que se deba liberar ninguna memoria; no veo que se realicen asignaciones dinámicas. Todo se hace con variables asignadas estáticamente. –

Cuestiones relacionadas