PDA

View Full Version : [C] client+server


Vault
29-03-2006, 23:36
Ciao a tutti, oggi ho iniziato a scrivere uno dei primi programmi che ci hanno proposto all'università... uno che inizia come client e cerca un server a cui connettersi, e se non lo trova, diventa server per gli altri futuri client. In pratica il primo che parte fa da server. Ora, a me ovviamente pare di aver scritto tutto giusto, ma quando lo faccio girare su linux si inchioda alla bind...
addr_init è una funzione che inizializza una struct sockaddr.

variabili:

int sd, new_sd, conn_err, bind_err, listen_err;
struct sockaddr_in mio_addr, altro_addr;
int mio_len = sizeof( mio_addr ), altro_len = sizeof( altro_len );


codice:

sd = socket( AF_INET, SOCK_STREAM, 0 );
conn_err = connect( sd, (struct sockaddr *) &altro_addr, altro_len );
if( conn_err == 0 ) { ...}
else {

close( sd );
addr_init( &mio_addr, PORT, INADDR_ANY );
sd = socket( AF_INET, SOCK_STREAM, 0 );
bind_err = bind( sd, (struct sockaddr *) &mio_addr, mio_len );
listen_err = listen( sd, MAXCONN );
new_sd = accept( sd, (struct sockaddr *) &altro_addr, &altro_len );
close( new_sd );
close( sd );

}


I miei tentativi:
1)all'inizio, avevo usato al posto di mio_addr e altro_addr le variabili cln_addr e srv_addr, ma non sono riuscito ad implementarle rispettando i loro nomi e il programma si inchiodava. usavo srv_addr sia nella parte client, che nella parte server (in addr_init e nella bind) :mbe: :confused:
2)non capisco ancora se è necessario chiudere e riaprire il socket sd...

Grazie a tutti!

sottovento
30-03-2006, 06:33
Ciao,
1 - quando parli del fatto che si inchioda alla bind, intendi che il programma resta bloccato li' o che la bind fallisce?
2 - il codice pubblicato e' una semplificazione? In pratica, controlli i valori di ritorno delle funzioni? Normalmente le funzioni da te usate, quando falliscono, ritornano -1 e settano la variabile errno, che contiene il codice dell'errore. Lo stampi ? Meglio ancora, puoi guardare cosa ti dice la perror (la quale stampa la stringa associata al codice di errore)?

Es.
res = funzione (...);
if (res < 0)
perror ("Errore nella funzione... "); // La stampa sara' seguita dal messaggio di errore "esteso"

Posta poi i risultati

High Flying
Sottovento

Vault
30-03-2006, 11:51
1) Intendo che la bind si inchioda, e sono costretto a terminare il programma.

2) Il codice è una semplificazione, con le printf di debug si allungava a dismisura. In particolare ho creato la funzione
void errore( int ); alla quale passare errno, e che mi fornisce, tramite strerror, gli errori delle funzioni che eseguo.

Generalmente ottengo questo output (vado a memoria):
Socket creato.
Impossibile connettersi.
Chiudo il canale.

Socket creato. /*stavolta tramite server */
Bind riuscita.
e qui si inchioda... so che la successiva listen è un interrupt, e quindi tra la printf "Bind riuscita" e la listen ne ho messa un'altra, "in attesa di connessioni", che però non compare mai :confused:
Però mi ricordo che ieri ho tolto un pezzo del codice finale del server, ed era arrivato fino alla fine, ovviamente con i dovuti errori perché mancavano dei pezzi. :mbe:

sottovento
30-03-2006, 15:44
Ciao,
quindi vedevi uscire "Bind riuscita". Immagino che tu abbia messo il controllo, per cui se la bind() non funziona, scrivi "non riuscita", altrimenti "riuscita", giusto?
Scusa se sono pedante, ma fa parte della ricerca degli errori, no?

A questo punto non capisco perche' dai la colpa alla bind e non a qualcosa che segue.

Piccola check list (se ti va di eseguirla. Sai, da pilota, e' obbligatorio eseguirle alla lettera...):
1) hai controllato il valore sd dopo la seconda socket ()?
2) hai controllato cosa contiene la mio_addr? SU ALCUNE PIATTAFORME LA DEVI REINIZIALIZZARE!!!
3) hai controllato bind_err e errno dopo l'esecuzione della bind? Per controllare, usa la perror (), e' piu' facile ed i suoi messaggi sono standard.
(res = bind (...); if (res < 0) perror ("Errore!"); )
4) Hai controllato la listen () alla stessa maniera del punto 2 ?
5) A questo punto, se tutto va bene, il programma deve rimanere bloccato nella accept() fintanto che qualcuno non si collega. Pertanto non e' necessario controllare oltre.
6) Hai pubblicato le perror()?

Spero ti possa essere utile.

High Flying
Sottovento

Vault
30-03-2006, 16:17
Allora oggi ho chiesto al mio prof di informatica e ho imparato che le "\n" vanno alla fine della printf, altrimenti potrebbero non essere visualizzate, come succedeva a me: quello che blocca è dunque la listen, ma siccome dopo la bind non stampava credevo fosse quella.

1) Adesso ho che il primo simm.exe ad essere avviato arriva con successo alla listen; il secondo però non vede il primo, e tenta anche lui di diventare server, ma la listen fallisce poiché il socket è già utilizzato. cosa c'è che non va?
2) io utilizzo la strerror come debug; ho guardato l'help della perror e non ho capito bene come funziona: devo inserirci la funzione che mi ha dato errore, ad esempio perror( "fork" ); ?

Grazie ancora!

AnonimoVeneziano
30-03-2006, 16:43
Ciao a tutti, oggi ho iniziato a scrivere uno dei primi programmi che ci hanno proposto all'università... uno che inizia come client e cerca un server a cui connettersi, e se non lo trova, diventa server per gli altri futuri client. In pratica il primo che parte fa da server. Ora, a me ovviamente pare di aver scritto tutto giusto, ma quando lo faccio girare su linux si inchioda alla bind...
addr_init è una funzione che inizializza una struct sockaddr.

variabili:

int sd, new_sd, conn_err, bind_err, listen_err;
struct sockaddr_in mio_addr, altro_addr;
int mio_len = sizeof( mio_addr ), altro_len = sizeof( altro_len );


codice:

sd = socket( AF_INET, SOCK_STREAM, 0 );
conn_err = connect( sd, (struct sockaddr *) &altro_addr, altro_len );
if( conn_err == 0 ) { ...}
else {

close( sd );
addr_init( &mio_addr, PORT, INADDR_ANY );
sd = socket( AF_INET, SOCK_STREAM, 0 );
bind_err = bind( sd, (struct sockaddr *) &mio_addr, mio_len );
listen_err = listen( sd, MAXCONN );
new_sd = accept( sd, (struct sockaddr *) &altro_addr, &altro_len );
close( new_sd );
close( sd );

}


I miei tentativi:
1)all'inizio, avevo usato al posto di mio_addr e altro_addr le variabili cln_addr e srv_addr, ma non sono riuscito ad implementarle rispettando i loro nomi e il programma si inchiodava. usavo srv_addr sia nella parte client, che nella parte server (in addr_init e nella bind) :mbe: :confused:
2)non capisco ancora se è necessario chiudere e riaprire il socket sd...

Grazie a tutti!


Mmmm , addr_init() ... ma tu vai al Poli di milano per caso?

Ciao

Vault
30-03-2006, 20:29
Sì! :D La funzione più precisamente sarebbe addr_initialize :cool:

sirus
30-03-2006, 21:32
Ragazzi...
ma al POLI di Milano al primo anno di Ing. Informatica abbiamo tutti la dispensa del Prof. Pelagatti (il mio prof.) per l'esame di Informatica 2 ?! :asd:

Vault in che scaglione sei? :sofico:

EDIT La tua citazione di Yoda in firma :cool: che bella cosa...

Vault
31-03-2006, 00:00
Sì, abbiamo tutti la dispensa di quello che è anche il mio prof :D
In info2 adesso nel Po-Z... va a finire che ti ho già visto!

{edit 01.43} Ho risolto il problema, era colpa di un invisibile errore di scrittura, che ovviamente non era anche un errore logico. L'unico indizio è stato l'errore di una connect, "invalid argument", invece che "connection refused" come deve essere... Grazie a tutti per l'aiuto!

sottovento
31-03-2006, 06:32
Sì, abbiamo tutti la dispensa di quello che è anche il mio prof :D
In info2 adesso nel Po-Z... va a finire che ti ho già visto!

{edit 01.43} Ho risolto il problema, era colpa di un invisibile errore di scrittura, che ovviamente non era anche un errore logico. L'unico indizio è stato l'errore di una connect, "invalid argument", invece che "connection refused" come deve essere... Grazie a tutti per l'aiuto!

Bene!
L'ultima cosa riguarda la perror (): in fase di debug e' molto utile.
La sintassi e':
perror ("messaggio qualsiasi");
Il messaggio verra' stampato a schermo, seguito poi dalla stringa di errore, ricavata dal valore di errno.

Per esempio:


f = open ("questofilenonesiste.txt", O_RDONLY);
if (f < 0)
perror ("Errore apertura questofilenonesiste.txt\n");


potrebbe stamparti:
Errore apertura questofilenonesiste.txt
:No such file or directory

o qualcosa di simile. Comodo, no?

High Flying
Sottovento

sirus
31-03-2006, 18:40
Sì, abbiamo tutti la dispensa di quello che è anche il mio prof :D
In info2 adesso nel Po-Z... va a finire che ti ho già visto!

{edit 01.43} Ho risolto il problema, era colpa di un invisibile errore di scrittura, che ovviamente non era anche un errore logico. L'unico indizio è stato l'errore di una connect, "invalid argument", invece che "connection refused" come deve essere... Grazie a tutti per l'aiuto!
Siamo compagni di corso a tutti gli effetti :asd: anche io sono nello scaglione Po - Z...

Filippo Sironi, se sei nella seconda metà dello scaglione ci si vede Lunedì in F11 per Elettrotecnica...

wisher
31-03-2006, 21:25
Siamo compagni di corso a tutti gli effetti :asd: anche io sono nello scaglione Po - Z...

Filippo Sironi, se sei nella seconda metà dello scaglione ci si vede Lunedì in F11 per Elettrotecnica...
ci sono anche io...
per la precisione sono quello che aiuta sirus a fare casino...
ciao
p.s.
se sei con codecasa ci sono io invece...

AnonimoVeneziano
31-03-2006, 21:31
Ragazzi...
ma al POLI di Milano al primo anno di Ing. Informatica abbiamo tutti la dispensa del Prof. Pelagatti (il mio prof.) per l'esame di Informatica 2 ?! :asd:

Vault in che scaglione sei? :sofico:

EDIT La tua citazione di Yoda in firma :cool: che bella cosa...

Ehm, io in classe ho il figlio di pelagatti, quel libro lo insultano tutti e lui ci rimane malissimo. Una volta il mio esercitatore ha detto in classe "Quello che ha scritto questo libro lo dovrebbero impiccare e poi lapidarne il corpo esanime" , parole testuali :sofico: Ogni giorno si diverte a trovare errori e suo figlio ... :mc:


Muahahaha, che risate :D

Ciao

wisher
31-03-2006, 21:36
ma l'hai mai visto come professore?
dopo un'ora sclera totalmente...
cmq il libro non mi pare malaccio (devo ammettere di non averlo rovinato troppo con lo studio però)
p.s.
fatti trovare al poli così spieghi al mio collega cos'è kde

sirus
31-03-2006, 21:59
Ehm, io in classe ho il figlio di pelagatti, quel libro lo insultano tutti e lui ci rimane malissimo. Una volta il mio esercitatore ha detto in classe "Quello che ha scritto questo libro lo dovrebbero impiccare e poi lapidarne il corpo esanime" , parole testuali :sofico: Ogni giorno si diverte a trovare errori e suo figlio ... :mc:


Muahahaha, che risate :D

Ciao
:asd: il libro tutto sommato non è male, se confrontato con il prof. Parte sempre bene, molto molto convinto di quello che sta facendo :p poi mano a mano che passa il tempo la decisione e le idee vanno scemando e si inizia a seguire poco il filo del suo discorso.

Per la parte di programmazione quel libro è proprio il minimo, non fa mezza gestione di errore, cita solamente funzioni come la perror e la variabile errno...

Per la parte sul sistema operativo non ci sono molte parti, che IMHO sono fondamentali... non spiega la differenza tra kernel micro e kernel monolitici per esempio :cry: insomma va poco a fondo!!!

Speriamo che in futuro ci sia modo di farne uno studio un tantino più approfondito :p

ci sono anche io...
per la precisione sono quello che aiuta sirus a fare casino...
ciao
p.s.
se sei con codecasa ci sono io invece...

Effettivamente io e wisher facciamo un po' di casino, oltretutto nelle prime file :banned:

ma l'hai mai visto come professore?
dopo un'ora sclera totalmente...
cmq il libro non mi pare malaccio (devo ammettere di non averlo rovinato troppo con lo studio però)
p.s.
fatti trovare al poli così spieghi al mio collega cos'è kde
Colgo l'occasione di annunciare che il mio PC1 è FULLED LINUX BASED (ARCH) e ovviamente c'è GNOME perché io KDE proprio non lo posso vedere :O

HayArms, se ci becchiamo ti mostrerò le vie di GNOME e ti illuminerò la via, KDE è il lato oscuro del desktop environment :rotfl: