2010-01-14 7 views
16

Ho un server con un socket in ingresso da un client. Ho bisogno di ottenere l'indirizzo IP del client remoto. Provato a cercare google per in_addr ma è un po 'fastidioso. Qualche suggerimento?Ottenere l'indirizzo di origine di una connessione socket in entrata

+0

in_addr è IPv4-specifici, in ogni caso – bortzmeyer

+0

vedi funzione inet_ntoa (..) in linux .. 'uomo inet_ntoa'. è più facile di inet_ntop secondo me e ha bisogno di includere arpa/inet.h. ecco un esempio: http://www.binarytides.com/programming-udp-sockets-c-linux/ – mhk

risposta

32

È necessaria la funzione getpeername. La grande guida di Beej alla rete ha un page about it. Ecco un esempio di codice da lì:

// 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. Tuttavia, non dobbiamo liberare memoria per questo? – iammilind

+1

Ho notato che 'struct sockaddr_in * s' ombreggia il socket' s' nello scope esterno. Avere una variabile ombreggiata non è l'ideale. –

+0

c'è un modo per ottenere il socketDescriptor dall'indirizzo – Bionix1441

1

Dal momento che si dice che è una connessione in entrata da un client, come alternativa al getpeername si può solo salvare l'indirizzo che è stato restituito dalla chiamata accept(), nel secondo e terzo parametri.

9

Supponendo che si utilizzi accept() per accettare le connessioni socket in entrata, getpeername() non è necessario. Le informazioni sull'indirizzo sono disponibili tramite il 2 ° e il 3 ° parametro della chiamata accept().

Qui è la risposta di Eli modificato per farlo senza 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 per l'uso diretto di 'accept()'. Tuttavia, non dobbiamo liberare memoria per questo? – iammilind

+3

@iammilind: Non penso che sia necessario liberare memoria: non riesco a vedere alcuna allocazione dinamica eseguita. È tutto fatto con variabili allocate staticamente. –

Problemi correlati