Repository 32bit  Forum
Repository 64bit  Wiki

[C]Connessione server/client "casuale"

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

[C]Connessione server/client "casuale"

Messaggioda boh » mar mar 25, 2008 19:53

Allora ho scritto due programmi che emulano il modello server/client:

Client:
Codice: Seleziona tutto
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>


#define PORT 4000
#define IP 15

int main(int argc, char** argv)
{
   int sd, error;
   struct sockaddr_in server_addr, mio_addr;
   int mio_addr_len = sizeof(mio_addr);
   char ip[IP] = "127.0.0.1";
   
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons((u_short)PORT);
   server_addr.sin_addr.s_addr = (long)inet_addr(ip);
   
   sd = socket(AF_INET, SOCK_STREAM, 0);
   error = connect(sd, &server_addr, sizeof(server_addr));
   
   if (error==0) {
      printf("Connessione stabilita! \n");
      getsockname(sd,  &mio_addr, &mio_addr_len);
      printf("Il mio port e': %i \n", ntohs(mio_addr.sin_port));
   }
   
   else
      printf("Fallito!\n");
      
   close(sd);
   
   return 0;
}


Server:
Codice: Seleziona tutto
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 4000
#define MAXCONN 5

int main(int argc, char** argv)
{
   int sd, new_sd;
   struct sockaddr_in server_addr, client_addr;
   int client_len=sizeof(client_addr);
   
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons((u_short)PORT);
   server_addr.sin_addr.s_addr = INADDR_ANY;
   
   sd = socket(AF_INET, SOCK_STREAM, 0);
   bind(sd, &server_addr, sizeof(server_addr));
   listen(sd, MAXCONN);
   printf("In attesa sul mio port %i \n", ntohs(server_addr.sin_port));
   
   new_sd = accept(sd, &client_addr, &client_len);
   
   printf("Ho accettato la connessione \n");
   printf("dal client con port: %i \n", ntohs(client_addr.sin_port));
   close(new_sd);
   close(sd);
   
   return 0;
}


Il problema non è che non funzionano, è che funzionano quando vogliono loro!
E' ovvio che c'è un problema ma non riesco a capire qual'è!
Praticamente avvio il server, poi il client, e tutto fila liscio, comunicano; ritento subito dopo e la connessione non avviene più.
Qualcuno sa spiegarmi dove ho sbagliato?
"Be yourself. Everyone else is already taken." ~ Oscar Wilde
Avatar utente
boh
Linux 2.6
Linux 2.6
 
Messaggi: 964
Iscritto il: gio set 15, 2005 23:00
Località: Milano
Slackware: 14.1 (x64)
Kernel: 3.14.1
Desktop: KDE 4.13.3

Re: [C]Connessione server/client "casuale"

Messaggioda Blizzard » mar mar 25, 2008 20:08

ciao
a parte che ad occhio il server mi sembra un tantino strano. È fatto per accettare 5 connessioni ma al massimo ne accetta una e poi termina.
Adesso non ho letto bene il codice, comunque se cerchi le slides di qualche corso di laboratorio di sistemi operativi anche di quello della mia università (univaq) dovresti arrivare a codici funzionanti. Io stesso li ho utilizzati.

Ciao
Gio
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: [C]Connessione server/client "casuale"

Messaggioda boh » mar mar 25, 2008 20:55

Ma il codice proviene da un libro del mio corso :D
L'unica modifica che ho apportato è nel client, in cui lui usava argv[1] ad un certo punto, e mi andava in seg.
Nonostante questo il tutto funziona, quello che volevo capire era da cosa poteva dipendere che ogni tanto si mettono in comunicazione e altre volte no :-k
"Be yourself. Everyone else is already taken." ~ Oscar Wilde
Avatar utente
boh
Linux 2.6
Linux 2.6
 
Messaggi: 964
Iscritto il: gio set 15, 2005 23:00
Località: Milano
Slackware: 14.1 (x64)
Kernel: 3.14.1
Desktop: KDE 4.13.3

Re: [C]Connessione server/client "casuale"

Messaggioda ksniffer » mar mar 25, 2008 22:09

Se dici precisamente cosa succede posso provarci io a vedere cosa non va. Spiega passo passo qual è il problema.

" si mettono in comunicazione e altre volte no"... Che vuol dire? Il server parte? si mette in ascolto?
Avatar utente
ksniffer
Linux 2.6
Linux 2.6
 
Messaggi: 540
Iscritto il: lun lug 30, 2007 12:18
Kernel: 2.6.34
Desktop: KDE 4.4.4
Distribuzione: ArchLinux

Re: [C]Connessione server/client "casuale"

Messaggioda alessiodf » mar mar 25, 2008 23:31

boh ha scritto:Ma il codice proviene da un libro del mio corso :D
Cambia libro!
Avatar utente
alessiodf
Linux 2.6
Linux 2.6
 
Messaggi: 823
Iscritto il: ven ott 14, 2005 20:04
Località: Roma
Slackware: current
Kernel: 2.6.26.4
Desktop: Kde 4.1

Re: [C]Connessione server/client "casuale"

Messaggioda Dani » mar mar 25, 2008 23:47

boh ha scritto:Praticamente avvio il server, poi il client, e tutto fila liscio, comunicano; ritento subito dopo e la connessione non avviene più.
Qualcuno sa spiegarmi dove ho sbagliato?


Sbagli nel non verificare che la chiamata a bind() sia avvenuta con successo.
Dopo la chiusura della connessione la porta su localhost rimane in TIME_WAIT per un po', quindi se non passa un certo lasso di tempo eventuali nuove bind() falliranno.

Codice: Seleziona tutto
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 4000
#define MAXCONN 5

int main(int argc, char** argv)
{
   int sd, new_sd;
   struct sockaddr_in server_addr, client_addr;
   int client_len=sizeof(client_addr);
   
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons((u_short)PORT);
   server_addr.sin_addr.s_addr = INADDR_ANY;
   
   sd = socket(AF_INET, SOCK_STREAM, 0);
   
   while (bind(sd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
   {
   printf ("Chiamata bind() fallita, pausa di 3 sec.\n");
   usleep (3000000);
   }
   
   listen(sd, MAXCONN);
   printf("In attesa sul mio port %i \n", ntohs(server_addr.sin_port));
   
   new_sd = accept(sd, (struct sockaddr*) &client_addr, &client_len);
   
   printf("Ho accettato la connessione \n");
   printf("dal client con port: %i \n", ntohs(client_addr.sin_port));
   close(new_sd);
   close(sd);
   
   return 0;
}

Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C]Connessione server/client "casuale"

Messaggioda ildiama » mer mar 26, 2008 0:16

Non sono sicuro al 100 %, ma secondo me quello della bind() è un falso problema, anche perché per come è adesso il codice dopo 1 connessione server e client si chiudono.
Se ho ben capito il tuo problema (anche qui, non 100%) secondo me dovresti risolvere con un ciclo sulla accept() del server. Qualcosa tipo
Codice: Seleziona tutto
while((new_sd = accept(sd, &client_addr, &client_lent)) == -1);

Prova e fai sapere. E in bocca al lupo. Per cose così, ci vuole sempre...
Avatar utente
ildiama
Linux 2.6
Linux 2.6
 
Messaggi: 536
Iscritto il: mar dic 27, 2005 16:49
Località: Senigallia
Slackware: mine
Kernel: 2.6.alto..
Desktop: KDE4

Re: [C]Connessione server/client "casuale"

Messaggioda Dani » mer mar 26, 2008 0:25

Se bind() fallisce il socket resta senza nome, di conseguenza accept() non potrà mai andare a buon fine.
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C]Connessione server/client "casuale"

Messaggioda ildiama » mer mar 26, 2008 0:54

Dani ha scritto:Se bind() fallisce il socket resta senza nome, di conseguenza accept() non potrà mai andare a buon fine.


Hai ragionissima Dani. Con le mie parole volevo intendere che nel codice scritto da lui, la bind() del server moooolto difficilmente fallirebbe e che eventuali problemi di connessione sono (secondo me) dovuti ad un timeout sì, ma della accept().
Avatar utente
ildiama
Linux 2.6
Linux 2.6
 
Messaggi: 536
Iscritto il: mar dic 27, 2005 16:49
Località: Senigallia
Slackware: mine
Kernel: 2.6.alto..
Desktop: KDE4

Re: [C]Connessione server/client "casuale"

Messaggioda Dani » mer mar 26, 2008 1:00

Boh ha detto "ritento subito dopo e la connessione non avviene più", quindi sono convinto al 99% che il problema sia dovuto proprio al fallimento della funzione bind(), per il motivo detto prima.
Prendi il codice di boh, compilalo ed avvialo piu' volte. Prova quindi a telnettarti su localhost:4000, dopo ogni avvio del server. Poi prova con quello che ho postato prima, che è lo stesso identico a parte il while() sulla funzione incriminata e vedrai che finchè su localhost la porta del programma resta in TIME_WAIT bind() non ne vorrà sapere :)
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C]Connessione server/client "casuale"

Messaggioda ildiama » mer mar 26, 2008 13:16

Adesso ho capito il problema di Boh! #-o
Ha ragione Dani... il mio suggerimento resta valido per il time_out della accept(), cioè per un lungo tempo di attesa fra avvio del server e avvio del client.
Avatar utente
ildiama
Linux 2.6
Linux 2.6
 
Messaggi: 536
Iscritto il: mar dic 27, 2005 16:49
Località: Senigallia
Slackware: mine
Kernel: 2.6.alto..
Desktop: KDE4

Re: [C]Connessione server/client "casuale"

Messaggioda boh » mer mar 26, 2008 13:17

Credo che l'intuizione di Dani sia corretta!
Solo non ho capito cosa faccia esattamente quel ciclo while, e perchè risolve il problema.
Scusate sono alle prime armi con la programmazione di rete (l'ho presa in mano ieri la prima volta).
"Be yourself. Everyone else is already taken." ~ Oscar Wilde
Avatar utente
boh
Linux 2.6
Linux 2.6
 
Messaggi: 964
Iscritto il: gio set 15, 2005 23:00
Località: Milano
Slackware: 14.1 (x64)
Kernel: 3.14.1
Desktop: KDE 4.13.3

Re: [C]Connessione server/client "casuale"

Messaggioda Dani » mer mar 26, 2008 16:43

Il ciclo semplicemente chiama bind() finchè la funzione non termina con successo, facendo una pausa di tre secondi tra una chiamata e l'altra. Quando il tuo server termina la connessione rimane comunque attiva per un certo lasso di tempo, quindi la porta usata dal tuo server rimane in uso e di conseguenza bind() fallisce, il socket resta senza nome e il server non potra' accettare connessioni.
Per forzare il successo di eventuali chiamate a socket()/bind() dovresti usare SO_REUSEADDR tra le opzioni del socket, ma non so fino a che punto sia conveniente :roll:
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti