C server con i thread

di il
15 risposte

C server con i thread

Salve ragazzi ho bisogno di chiarimenti.
Sto costruendo un server concorrente con i thread, ma ci sono delle cose che non riesco a fare.
Prima di tutto quando ci si connettere al server questo offrirà queste funzioni
- Login ( si effettua appena ci si connette al server altrimenti non si va avanti)
- Lettura recensioni hotel
- Lettura lista hotel
ora il mio problema è questo quando si connettono piu client,il processo server genera piu thread quanti sono i client,e qui la sincronizzazione mi riesce difficile.
Se ad esempio ad un client gli faccio fare il login e dopo un po avvio un altro client,quest ultimo non partirà dal login ma il programma continua da dove si trova l'altro client e un altra cosa,visto che questi comunicano tramite socket ogni volta che scrivo o leggo da socket devo usa questa sintassi per la mutua esclusione?
mutex lock
leggi
mutex unlock
siccome due processi non possono leggere e scrivere contemporaneamente.
Grazie per la pazienza

15 Risposte

  • Re: C server con i thread

    Non lo so se ho comprenso bene i problemi sono due.
    1) il secondo utente non si logga correttamente ma passa perché qualcun altro ha fatto il login
    2) hai un problema con i mutex

    Spiegano meglio per favore
  • Re: C server con i thread

    Prima di tutto spiega in quale contesto/ambiente stai lavorando ....
  • Re: C server con i thread

    Semplicemente il server avrà un solo socket in listen, a questo punto il client si connette , il server crea il nuovo thread ed accetta la connessione sul nuovo thread in modo che il client1 comunichi col server tramite il thread 1, nel frattempo il processo principale era tornato su listen e un secondo client si connette al serve e di nuovo si esegue la stessa procedura.
    A questo punto puoi dialogare simultaneamente senza bisogno di nessun genere di sincronismo, il thread1 leggerà e scriverà solo ed esclusivamente al client1, e cosi via per i sucessivi utenti.
    Altresi è vero che i vari thread del server potrebbero accedere a funzionalità che debbano essere sincronizzate, ad esempio l'eliminazione di un file o altre cose simili, in questo caso allora si, devi sincronizzare i thread in modo che non collidano tra di loro.
  • Re: C server con i thread

    Vbextreme ha centrato il punto,chiedo scusa agli altri se sono stato poco chiaro.Comunque sto lavorando su linux.
    Come posso risolvere il problema che quando un client esegue il login e connetto un altro client quest'ultimo va gia "avanti" nel programma invece di partire dall'inizio.E poi quando ogni client comunica con il socket non ha bisogno dei mutex?
    p.s ho provato a togliere qualche mutex che avevo messo qua e la e ti riporto il risultato
    connetto un client gli faccio fare il login in questo modo:
    server >digita il nome utente
    client >nome utente
    server >digita password
    client >password
    a questo punto se connetto un client non partirà dal login ma da dopo il login
  • Re: C server con i thread

    Se stai lavorando con linux sei sicuro di usare più thread? O più processi?

    In ogni caso, se mostrassi il codice sarebbe tutto più semplice ...
  • Re: C server con i thread

    Il codice è lungo metto solo alcune parti?
  • Re: C server con i thread

    Da quanto ho capito ogni thread dovrebbe avere il suo socket allroa come è possibile che un thread scrive sul socket di un altro? ho provato a mettere un mutex quando vado a impostare la variabile sd(che contiene il socket) ma niente non cambia la cosa perfavore se sapete qual è il problema datemi una mano
  • Re: C server con i thread

    Perché i thread condividono i dati.
  • Re: C server con i thread

    Lo sò per questo ho messo il mutex? non dovrebbe risolvere la cosa?
  • Re: C server con i thread

    Purtroppo la programmazione concorrente non puo' essere fatta per tentativi, e soprattutto non si possono inserire oggetti di sincronizzazione a casaccio.

    Pena comportamenti imprevedibili, o blocchi totali dovuti ad abbracci mortali

    Ad esempio, dalla descrizione che hai dato del problema, non ti servono minimamente i mutex: ogni thread gestisce un proprio client, e non interagisce con gli altri client.

    Da una prima analisi e' evidente che tu stai ragionando ancora in termini di programmazione sequenziale:

    1) fai il join solo con l'ultimo thread e non con tutti quelli che hai creato
    2) utilizzato il mutex in n-mila posti dove non serve minimamenre
    3) utilizzo di unlock senza il corrispondente lock
    4) ecc ...

    E' evidente che sei alle prime armi, e che ti manca il background per questo tipo di programmazione. E scrivere programmi concorrenti e' complicato anche per persone con esperienza. E' un argomento che si affronta solo dopo che si sa programmare bene!



    Consiglio:

    0) cancella tutto e ricomincia da zero
    1) fai una prima implementazione SENZA THREAD, con una sola socket ed un solo client
    2) quando hai la versione funzionante SALVALA e cancella tutto
    3) studiati (possibilmente su un libro e non a spizzichi e bocconi su Internet) i thread e fai degli esercizi con dei programmini molto semplici che poi via via renderai piu' complicati
    4) quando hai capito come funzionano i thread SALVA GLI ESERCIZI e cancella tutto
    5) solo ora dovresti avere abbastanza informazioni per mettere tutto assieme

    In questo momento stai affrontando un problema che e' troppo complicato per le tue attuali conoscenze.

    Ti servono diversi giorni per far funzionare il programmino in versione monothread, e diversi giorni per capire come funzionano i thread.
  • Re: C server con i thread

    Apprezzo il tuo consiglio davvero e non posso fare altro che darti ragione su tutto ma il programmino che ho fatto prima era con la fork ora però il professore mi ha chiesto di trasformarlo con i thread e non ho tempo siccome la settimana prossima devo consegnarlo,non è che potresti indicarmi perchè si viene a creare quell errore?
  • Re: C server con i thread

    Scrivo questo aimhè dopo aver già scritto il messaggio:
    Il crossposting è una tecnica vietata e poco carina nel rispetto di chi ti aiuta.







    Naturalmente senza tutto il codice non si può trarre nessuna conclusione, leggendo quello che hai posato però è quasi chiaro che il problema è nella connessione e nella comunicazione,bisognerebbe metter un paio di printf in qua e la (naturalmente non a caso ma in punti ben precisi) per capire se è la fase di connessione o la fase di lettura e scrittura tra i socket il problema.
    Potrebbe essere anche il cliente.
    Insomma con tutto il codice avremmo potuto eseguirlo sulle nostre macchine e testare i problemi.
    Prima però di postarlo per favore ripuliscilo da tutta l'immondizia!
    ecco ad esempio il tuo codice lievemente ripulito.
    
    //presumo ci sia un Main e un listen che sarebbe stato carino vedere
    
    	while(1)
    	{
    		if((connect_fd=accept(sd,NULL,NULL))==-1)
    		{
    			perror("errore di connessione");
    			exit(0);
    		}
    		pthread_create(&tid,NULL,menu,(void *) &connect_fd);
    	}
    	
    	//con un while 1 e un exit in errore dall'accept tutto quello che c'era qui sotto 
    	//non serve a nulla perchè non verrà mai eseguito.
    	return 0;//solo per cordialità
    }
    
    // questa è la funzione menu (handler del thread) metto solo una piccola parte perchè ripeto il codice
    // è lungo e poi è simile nel senso che ogni caso fa una lettura e scrittura da socket
    
    void *menu(void *arg)
    {
    	int *sd= (int *) arg;
        char leggi[50],buffer[512],path[20],voto,trova[5],user[10];
        int indice,fd,contatore=0;
        float media=0;
            
        login(*sd,user);
        
        do
        {
    		contatore=0;
            //memset(path,0,sizeof(path)); INUTILE
            strcpy(path,path_hotel);
            do
            { 
                 comunica(*sd,"\n benvenuto!\n che cosa vuoi fare ora?\n(1)lista hotel valutati con voto medio\n(2)leggere valutazioni di un  hotel\n(3)scrivere una propria valutazione\n(4)disconnetti\n(5)esci\n");
                 read(*sd,leggi,1);
                 indice=atoi(leggi);
            }while(indice<1 && indice>5);
            
            switch(indice)
            {
                 case 1: // stampa del file lista
                    //memset(buffer, 0, sizeof(buffer));
                    fd=open("hotel/lista",O_RDONLY);
                    write(*sd,"leggi",6);
                    // sleep(1); INUTILE LE SOCKET SONO BUFFERIZZATE
                    
                    //leggi e invii un carattere per volta usando un buffer da 512 byte?
                    //sarebbe piu logico inviare prima la dimensione del file al client
                    //poi inviare il file pacchettizzato, naturalmente quando il client
                    //sapendo quanto è grande il file sa in automatico quando finisce la transazione
                    while(read(fd,buffer,1)>0)
                    {
                       write(*sd,buffer,1); 
                    }
                    write(*sd,"#",1);
                    close(fd);
                 break;
            }
    //Da una parte manca la testa e dall'altra la coda...
    
    
    void login(int connect_fd,char user[])
    {
    	int fd,len_pswd=0;
        char buffer[50],password[50];
        char path[50];
        int err=0;
        char scelta[2];
        while(1)
        {
    		memset(user, 0, sizeof(user));
            err=0;
            
            comunica(connect_fd,"[R]egistrati o esegui il [L]ogin per poter vedere la lista degli hotel\n");
            read(connect_fd,scelta,1);
            
            if(scelta[0]=='l' || scelta[0]=='L')
            {
                 strcpy(path,path_user);
                 comunica(connect_fd,"inserisci l'user con cui vuoi eseguire il login\n");
                 
                 memset(buffer, 0, sizeof(buffer));//sicuramente messa per una cattivo invio dei dati dal client
                 read(connect_fd,buffer,50);
                 strcpy(user,buffer);
                 strcat(path,buffer); //ma path ? dove l'hai inizializzato?????????
                 
                 //Logica contorta! Modificata
                 
                 if( (fd=open(path,O_RDONLY)) <= 0 )
                 {
    				 comunica(connect_fd,"il nome utente non esiste\n");
    				 continue;
    			 }
                 
                 do
                 {
    				comunica(connect_fd,"Inserisci la password,attenzione la password deve contenere 7 caratteri\n");
    				memset(buffer, 0, sizeof(buffer));//ci risiamo...
    				read(connect_fd,buffer,50);
                 }while(strlen(buffer)<7 || strlen(buffer)>7);
                    
                 read(fd,password,7);
                 close(fd);
                    
                 // la parte qui sotto era da manicomio!
                    
                 if( !strcmp(password,buffer) ) 
    				{break;}
                 else 
    				{comunica(connect_fd,"password sbagliata!\n");}
    		}
          //pthread_mutex_unlock(&sem);
       }
    }
    
  • Re: C server con i thread

    Permettimi di dire due parole allora:
    Prima di accusare è meglio che pensiate cosa spinge qualcuno a scrivere la richiesta di "aiuto" ad un altra persona.
    Comunque sono riuscito a risolvere DA SOLO quella cosa,ho intuito il problema e ho risolto.Ora però purtroppo trovo difficoltà su un altra cosa,ad un certo punto del programma dovrei mandare un segnale a tutti i thread ho letto della sys call Kill ma serve il pid del processo,c'è un altro modo?
    ah e ci tengo a precisare che non ho postato tutto il codice siccome è gia stato corretto dal mio professore mi ha solo chiesto di provarlo a fare con i thread
  • Re: C server con i thread

    Non accuso nessuno,dico solo che i forum hanno un regolamento e io mi aspetto che si cerchi di rispettarlo.
    P.s. hai nuovamente violato il regolamento,nuova domanda nuovo thread.
Devi accedere o registrarti per scrivere nel forum
15 risposte