PDA

Visualizza la versione completa : [C] Uso di socket e determinazione indirizzo IP reale


Valx2
10-11-2007, 18:27
Ciao a tutti,
brevemente introduco il mio problema:

Ambito: programma client-server (comunicazione via socket su sistema operativo LINUX)

Dinamica semplificata: il client contatta il server, gli lascia il suo indirizzo IP e la porta d'ascolto... poi termina la connessione e si mette in attesa che il server lo ricontatti.

Problema: Non riesco a fare in modo che il client lasci al server l'indirizzo IP reale della scheda di rete (L'indirizzo di rete locale es. 192.168.1.10)... Tutte le volte che provo a leggere l'IP assegnato al processo client vengono fuori valori assurdi ( formattati in dotted quad, ma roba tipo 16.144.3.2 )...
Dopodiche' se rilancio il processo client, esso assume un indirizzo diverso.

Purtroppo non ho molta esperienza nella programmazione client server,
ma manuali dicono di usare getsockname(), tuttavia utilizzando tale funzione il risultato e' quello sopradescritto.

Ogni aiuto e' ben accetto, grazie molte in anticipo!

oregon
10-11-2007, 19:10
E il codice che usi?

Valx2
13-11-2007, 11:28
Il codice che uso e' un semlice programmino client - servert...
Il problema credo sia nel client, infatti se provo a stampare il contenuto di mio_addr.in_addr mi restituisce dei valori assurdi
Li riporto qui di seguito:

CLIENT

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* Numero di Port sul quale il client richiede la connessione */

#define PORT 4000

/* Funzione per inizializzare gli indirizzi */

void addr_initialize(struct sockaddr_in *indirizzo, int port, long IPaddr)
{
indirizzo->sin_family = AF_INET;
indirizzo->sin_port = htons((u_short) port);
indirizzo->sin_addr.s_addr = IPaddr;
}

/* Programma principale */

void main(int argc, char* argv[])
{
int sd;
struct sockaddr_in server_addr;
struct sockaddr_in mio_addr;
int mio_addr_len=sizeof(mio_addr);
int error;
addr_initialize(&server_addr, PORT, inet_addr(argv[1]));
sd=socket(AF_INET,SOCK_STREAM,0);
error=connect(sd,(struct sockaddr*) &server_addr, sizeof(server_addr));
if (error==0)
{
printf("Ho eseguito la connessione\n");
getsockname(sd, &mio_addr, &mio_addr_len);
printf("il mio port e': %d\n\n",ntohs(mio_addr.sin_port));
printf("il mio IP Ŕ: %s", inet_ntop(AF_INET,mio_addr.sin_addr.s_addr,IP,INET _ADDRSTRLEN));
close(sd);
}

else printf("%s","\nErrore di connect\n\n");
close(sd);
}



SERVER



#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>


#define PORT 4000 >


#define MAXCONN 5

void addr_initialize(struct sockaddr_in *indirizzo, int port, long IPaddr)
{
indirizzo->sin_family = AF_INET;
indirizzo->sin_port = htons((u_short) port);
indirizzo->sin_addr.s_addr = IPaddr;
}


void main(int argc, char * argv[])
{
int sd,new_sd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_len=sizeof(client_addr);
addr_initialize(&server_addr, PORT, INADDR_ANY);
sd=socket(AF_INET,SOCK_STREAM,0);
bind(sd,(struct sockaddr*) &server_addr,sizeof(server_addr));
listen(sd,MAXCONN);
printf("Mi pongo in attesa di richieste di connessione\n");
printf("sul mio port: %d\n", ntohs(server_addr.sin_port));
new_sd=accept(sd,(struct sockaddr*) &client_addr, &client_len);
printf("\n\nHo accettato una connessione\n");
printf("dal client con port: %d\n\n", ntohs(client_addr.sin_port));
close(new_sd);
close(sd);
}

oregon
13-11-2007, 13:30
Nel Client devi scrivere



inet_ntop(AF_INET, &mio_addr.sin_addr, IP, INET_ADDRSTRLEN);
printf("il mio IP Ŕ: %s\n", IP);


e non come hai fatto ...

Valx2
13-11-2007, 14:23
Grazie molte e scusa se approfitto ancora della tua disponibilitÓ...
il fatto che adesso mi dia come IP l'indirizzo di loopback (127.0.0.1) Ŕ causato da un errata inizializzazione del socket da parte mia oppure sto usando male la funzione getsockname?
Cercando sui manuali, infatti, si evince che la funzione getsockname restituisce l'indirizzo locale a cui e' associato il socket (e quindi in linea teorica l'indirizzo di loopback Ŕ corretto anche se di dubbia utilitÓ in questo caso)...
Esiste quindi la possibilitÓ di ottenere tramite queste funzioni l'indirizzo IP della scheda di rete da cui partono/arrivano le comunicazioni, oppure devo cambiare radicalmente tecnica per ottenerli?

Valx2
13-11-2007, 17:42
Ecco sono riuscito a capire il perche':
se lancio il comando client con indirizzo di connessione al server 127.0.0.1, lui lavora sull'indirizzo di loopback della macchina, quindi interpreta anche l'indirizzo del client da cui viene lanciato il comando di connessione come quello di loopback...
Utilizzando l'indirizzo d'interfaccia della scheda invece funziona perfettamente. Ho anche provato ad utilizzare client e server su macchine diverse!

Probabilmente era scontato, ma proprio non mi e' venuto in mente prima!

Cmq ti ringrazio molto Oregon, sei stato preziosissimo!

billiejoex
14-11-2007, 02:02
Ricorda che oltra a getsockname() hai anche getpeername() che ti ritorna l'indirizzo remoto a cui Ŕ connesso il socket locale.

Loading