IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

POSIX C Discussion :

Programmation réseau : socket et thread


Sujet :

POSIX C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut Programmation réseau : socket et thread
    Bonjour,

    je dois coder un système de ventes aux enchères en C pour le serveur et en java (interface graphique) pour le client
    donc en gros, dès qu'il y a un accept() au niveau du serveur, on lance un thread avec en paramètre le socket renvoyé par le accept()
    Pour l'instant ça fonctionne.
    Dans la méthode associée au thread, on récupère une action (avec un switch) que le client a envoyé(par exemple 1 correspond à une inscription, 2 à une identification, etc)
    Donc le serveur récupère bien ces informations avec un recv() quand le client valide son inscription.
    Le problème se situe au niveau de la réponse du serveur, lorsque que le client clique par exemple pour valider son inscription, le serveur recoit bien les informations mais ici l'application client freeze et ne semble rien recevoir (readLine() bloquant au niveau du client ou send bloquant au niveau du serveur?)
    Par contre l'application ne freeze pas (je reçois quelque chose au niveau du client) lorsque, dans la routine du thread, j'enleve le commentaire //sortie=TRUE; mais le problème c'est que le thread se termine et qu'on forme le socket client et donc aucun dialogue possible par la suite.
    voici les extraits de code du serveur et du client (désolé c'est long)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    void* inscription(void *param)
    {
    	char buf [1024];
    	struct Client monClient;
    	int action, sd_client;
    	sd_client=*(int*)param;
    	bool sortie=FALSE;
    	while(!sortie)
    	{
    		memset(buf,0,sizeof(buf));
    		recv(sd_client,buf,sizeof(buf),0);
     
    		//fprintf(stdout,"buf-> %s",buf);	
    		char *Tab = (char *) malloc ((1024+1) * sizeof (char));
    		for (z = 0; z < 1024; z++)
    			Tab [z] = buf[z];
    		Tab [z+1] = '\0';
     
    		//action=atoi(strtok(Tab,"|"));	
    		action=atoi(Tab);
    		switch(action)
    		{
    			case 0: break;
    			case 1:
    				if(recv(sd_client,buf,sizeof(buf),0) != -1)
    				{
    					for (z = 0; z < 1024; z++)
    						Tab [z] = buf[z];
    					Tab [z+1] = '\0';
    					//fprintf(stdout,"%s","inscription");
    					monClient.Nom=strtok(Tab,"|");
    					monClient.Prenom=strtok(NULL,"|");
    					monClient.Adresse=strtok(NULL,"|");
    					monClient.Email=strtok(NULL,"|");
    					monClient.Telephone=strtok(NULL,"|");
    					monClient.IP=strtok(NULL,"|");
    					monClient.MP=strtok(NULL,"|");  
    					fprintf(stdout,"%s\n",monClient.Nom);
    					fprintf(stdout,"%s\n",monClient.Prenom);
    					fprintf(stdout,"%s\n",monClient.Adresse);
    					fprintf(stdout,"%s\n",monClient.Email);
    					fprintf(stdout,"%s\n",monClient.Telephone);
    					fprintf(stdout,"%s\n",monClient.IP);
    					fprintf(stdout,"%s\n",monClient.MP);
     
    					deja_inscrit=0;
    					for(i=0;i<nb_clients_inscrits;i++)
    					{
    						if(strcmp(Clients[i].Email,monClient.Email) == 0)
    						{
    							deja_inscrit=1;
    						}
    					}
     
    					if(deja_inscrit == 0)
    					{
    						nb_clients_inscrits++;
    						Clients=realloc(Clients,nb_clients_inscrits*sizeof(monClient));
    						Clients[nb_clients_inscrits-1]=monClient;
    						fprintf(stdout,"Inscription reussie pour %s\n",Clients[nb_clients_inscrits-1].Nom);
    						fprintf(stdout,"%s",msg);
    						strcpy(test,"Inscription reussie!");
    						//sortie=TRUE;
    					}
    					else
    					{
    						fprintf(stdout,"Inscription KO pour %s\n",monClient. Nom);
    						fprintf(stdout,"%s",msg);
    						strcpy(test,"Vous etes deja inscrit!");
    					}
     
    					fprintf(stdout,"Nombre d'inscrits : %d\n", nb_clients_inscrits);
    					for(i=0;i<nb_clients_inscrits;i++)
    					{
    						fprintf(stdout, "mail  : %s\n", Clients[i].Email);
    					}
     
     
    					//n=write(sd_client,test,strlen(test));
    					if(send(sd_client,test, strlen(test),0) == -1)
    					{
    						perror("erreur send");
    					}
    					/*if(n < 0)
    					{
    						perror("erreur write");
    					}
    					else
    					{
    						fprintf(stdout,"message envoye -> %s",test);
    					}*/
    				}
    					break;
    			case 2:
    				[...]
    				break;
    			case 3:
    				[...]
    				break;
    		}
    	}//fin du while
    	close(sd_client);
    	pthread_exit(0);
    }
    Ensuite dans le main() j'ai ça (je déclare un socket + bind + listen juste avant)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    	while(1) /* Si demande de connexion ouvre une socket pour celle-ci */
    	{
       	msgsock = accept(sock, (struct sockaddr *)&emis,&lemis);
       	if (msgsock < 0) perror("accept");
    		else 
    		{
    			if (getsockname (msgsock,(struct sockaddr *)&emis, &lemis) < 0)
    			{
      	 			perror ("getsockname"); close (sock); return 1;
    			}
    			/* ntohs conversion entiers format réseau to hote */
    			printf ("Socket TCP emetteur %s port #%d\n", inet_ntoa(emis.sin_addr.s_addr), ntohs (emis.sin_port));
    			if (pthread_create(&thread_inscription, NULL,inscription, &msgsock) == -1)
    			{
    	  			perror("Unable to create the thread");
    			}
     
     
    		}
     
    	}
    	close(sock);
    au niveau du client : "pred" me sert pour envoyer au serveur et "plec" me sert à lire ce qui vient du serveur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
       private void bt_valider_inscriptionActionPerformed(java.awt.event.ActionEvent evt) {
            String retour="";
     
            if(TestVariable(tf_nom.getText()) && TestVariable(tf_prenom.getText()) && TestVariable(tf_adresse.getText()) && TestVariable(tf_email.getText()) && TestVariable(tf_tel.getText()) && TestVariable(new String(tf_mdp.getPassword())))
            {
     
                try
                {
                    String ip="";
                    ip = InetAddress.getLocalHost().getHostAddress();
                    leClient=new structClient();
                    leClient.setAdresse(tf_adresse.getText());
                    leClient.setEmail(tf_email.getText());
                    leClient.setIP(ip);
                    leClient.setNom(tf_nom.getText());
                    leClient.setPrenom(tf_prenom.getText());
                    leClient.setTel(tf_tel.getText());
                    leClient.setMP(new String(tf_mdp.getPassword()));
                    pred.println(INSCRIPTION);
                    pred.println(leClient.getNom()+"|"+leClient.getPrenom()+"|"+leClient.getAdresse()+"|"+leClient.getEmail()+"|"+leClient.getTel()+"|"+leClient.getIP()+"|"+leClient.getMP());          // envoi d'un message   */
                    System.out.println(leClient.getNom()+"|"+leClient.getPrenom()+"|"+leClient.getAdresse()+"|"+leClient.getEmail()+"|"+leClient.getTel()+"|"+leClient.getIP()+"|"+leClient.getMP());
     
                        retour=plec.readLine();
                        System.out.println("retour: "+retour+"\n");
     
                    if(retour.equals("Vous etes deja inscrit!"))
                    {
                        bt_valider_inscription.setEnabled(true);
                        //Deconnexion();
                        //if(!Connexion())
                        //{
                            JOptionPane.showMessageDialog(null,"Serveur pas en ligne");
                        //}
                    }
                    if(retour.equals("Inscription reussie!"))
                    {
                        //bt_valider_inscription.setEnabled(false);
                       // ActionsInscription.setEnabled(false);
                       // ActionDesinscription.setEnabled(true);
                    }
                    JOptionPane.showMessageDialog(null,retour);
                }
     
                catch(UnknownHostException e) { System.err.println(e); }
                catch(IOException e) { }
     
     
            }
            else
            {
                JOptionPane.showMessageDialog(null,"Un des champs n'est pas rempli");
            }
     
        }

  2. #2
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *Tab = (char *) malloc ((1024+1) * sizeof (char));
    		for (z = 0; z < 1024; z++)
    			Tab [z] = buf[z];
    		Tab [z+1] = '\0';
    Ca me paraît un peu suspect z+1 parce qu'en sortie de boucle ca vaut 1025 Tab[1025]=hors borne.

    je sais pas si recv ne place pas déja le /0 autant faire un calloc dans ce cas.


    Le send n'est pas bloquant au niveau du serveur mais cela peut échouer tu n'as pas un perror send qui s'execute ?

    Tu pourrais montrer comment tu déclares la variable test ?

    Pour la partie java il y a un forum où on pourrait mieux te répondre sinon il faut que tu montres comment tu construit ta variable plec.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    Pour l'histoire du 1025 regarde le malloc...
    Je sais que c'est du bidouillage mais ça marche, là n'est pas le problème.

    Non je n'ai pas de perror au moment du send() non plus!

    Pour la variable test j'ai Pour le plec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     socket = new Socket("127.0.0.1", 9999);
                   System.out.println("SOCKET = " + socket);
     
                plec = new BufferedReader(
                                       new InputStreamReader(socket.getInputStream())
                                       );
    Le problème n'est pas là non plus puisque je reçois bien quelquechose au niveau du client (une boite de dialogue affiche "inscription réussie") lorsque dans mon code dans le "case 1:" j'enlève le commentaire Si je remets le commentaire (on sort jamais de la boucle, on écoute sans cesse dans le thread), le client freeze.

  4. #4
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Pour l'histoire du 1025 regarde le malloc...
    Oui j'ai bien vu tu alloues 1024+1 octets donc des indices valides compris entre 0 et 1024 hors en sortant de ta boucle z=1024 et tu mets ton /0 à l'indice 1024+1 donc y'a un probléme

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 15
    Par défaut
    Ah bah oui j'avais meme pas fait gaffe...d'ailleurs c'est bizarre, ça marche puisque ça m'affiche bien les bonnes valeurs quand je découpe avec strtok

    Y'a peut être plus simple pour mettre les données d'un tableau de char dans un pointeur sur un char ?

  6. #6
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Citation Envoyé par roms712
    Ah bah oui j'avais meme pas fait gaffe...d'ailleurs c'est bizarre, ça marche puisque ça m'affiche bien les bonnes valeurs quand je découpe avec strtok

    Dans la pratique cela pourrait avoir des conséquences plus grave et jouait sur la stabilité de ton système.Qui as dis qu'un programme qui marche etait exempt d'erreur ?


    Citation Envoyé par roms712
    Y'a peut être plus simple pour mettre les données d'un tableau de char dans un pointeur sur un char ?
    Dans ton cas memcpy mais ta méthode est valable aussi c'est juste que tu débordes un peu.


    Pour la freeze(il faudra expliquer ce que tu appeles freeze d'ailleurs) il faut voir ce qui se passe vraiment parce qu'au départ tu dis que le client ne reçoit rien (tu te demandes même si readline est blocant) et d'un autre côté tu dis que ton client java t'affiche bien ta boite de dialogue (inscription réussi) alors que son appel ne vient qu'aprés ton readline....

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Programmation Socket et Thread
    Par seco102 dans le forum Threads & Processus
    Réponses: 4
    Dernier message: 24/05/2012, 16h29
  2. Réponses: 11
    Dernier message: 17/05/2012, 10h38
  3. [Jeu] - Programmation réseau <sérialisation,sockets,threads>
    Par ixabro dans le forum Développement
    Réponses: 5
    Dernier message: 02/02/2012, 22h18
  4. Pour débuter en programmation réseau
    Par durnambule dans le forum Développement
    Réponses: 3
    Dernier message: 20/06/2004, 22h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo