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
risposta
È 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);
+1. Tuttavia, non dobbiamo liberare memoria per questo? – iammilind
Ho notato che 'struct sockaddr_in * s' ombreggia il socket' s' nello scope esterno. Avere una variabile ombreggiata non è l'ideale. –
c'è un modo per ottenere il socketDescriptor dall'indirizzo – Bionix1441
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.
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);
+1 per l'uso diretto di 'accept()'. Tuttavia, non dobbiamo liberare memoria per questo? – iammilind
@iammilind: Non penso che sia necessario liberare memoria: non riesco a vedere alcuna allocazione dinamica eseguita. È tutto fatto con variabili allocate staticamente. –
in_addr è IPv4-specifici, in ogni caso – bortzmeyer
man getpeername
–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