Recupero IP / Porta dalla presa descrittore
Domanda
un clone di inetd in cui devo eseguire un server che stampa la IP e la porta del client connesso ad esso.
Come ho STDIN
sovrascrittura e STDOUT
con il descrittore di socket, mia soluzione iniziale per fare questo è stato quello di recuperare la struttura sockaddr_in
, che contiene le informazioni necessarie. Facendo questo con getsockname()
, tuttavia, sta tornando una struttura vuota, con tutti i bit impostati a 0.
Qualche idea di ciò che è sbagliato con il mio approccio? Ci sono altri approcci che posso usare per recuperare l'IP / porta?
Grazie
Soluzione
R .. ha sottolineato, è necessario utilizzare getpeername
. Sia che la funzione e getsockname
prendono un descrittore di file come primo argomento, non un torrente puntatore (FILE *
). Utilizzare fileno(stdin)
per ottenere il descrittore di file per l'input standard (o hard-code a STDIN_FILENO
, in quanto la costante).
Inoltre, l'ultimo argomento per getsockname
e getpeername
dovrebbe essere un puntatore a socklen_t
, non è una costante, e si dovrebbe utilizzare un sockaddr_in
per TCP / IP:
struct sockaddr_in peeraddr;
socklen_t peeraddrlen = sizeof(peeraddr);
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen);
Vedere un esempio completo qui .
Altri suggerimenti
Usa getpeername
. Ho il sospetto che il tuo problema è che sta tornando getsockname
le informazioni per il proprio lato (locale) della presa, che è probabilmente destinata a 0.0.0.0 (che significa che può accettare connessioni da qualsiasi interfaccia).
Modifica Credo di aver trovato il bug attuale lettura del codice. Questa linea è sbagliato:
getsockname(stdin, &addr, sizeof(addr));
funzioni ??Il getsockname
e getpeername
prendere un socklen_t *
( puntatore ) come terzo argomento, non un size_t
. Il compilatore dovrebbe essere dicendo su questo errore a meno che non si è dimenticato di includere un colpo di testa con il prototipo getsockname
. Inoltre, come si è già detto, stdin
non è corretto. Prova:
socklen_t len = sizeof addr;
getpeername(0, &addr, &len);
o (solo C99):
getpeername(0, &addr, (socklen_t[1]){sizeof addr});
Si dovrebbe anche essere il controllo del valore di ritorno; Se così fosse, si vedrebbe che è il ritorno errori.
Se avete bisogno di quelle informazioni per il client remoto, è necessario chiamare getpeername () .