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

Windows Discussion :

thread sous windows


Sujet :

Windows

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut thread sous windows
    salut

    Voila mon probleme: j'ai essayer de réer un tchat, d'abord le client envoie un message au serveur, puis plusieurs, puis le serveur répond, et enfin les deux ensembles. Or là problème: le serveur envoie 100 message (de salut0 à salut100) puis un 101° qui est "esc" et le client est chargé de récuperer tout les message jusqu'à ce quil trouve "esc". lorsque je fait une boucle de recv() directement dans le main, pas de problème. Mais lorsque je fait un thread, il reçoit plus rien.
    j'ai d'abord pensé que ça pouvait venir de la console, alors la reception se fait dans un fichier appelé conv.txt.

    Voici ce code:
    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
    105
    106
    107
    108
    109
    110
    111
    112
    113
    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    #include <time.h>
    #include <string.h>
    #include <windows.h>
    
    void wsa_start();
    void connecter(SOCKADDR_IN *info_source, SOCKET socket);
    void envoyer(SOCKET socket);
    unsigned long WINAPI recevoir(void* socket);
    
    int main(int argc, char *argv[])
    { 
    
    wsa_start();
    
    SOCKET socket_perso = socket(AF_INET, SOCK_STREAM, 0);
    printf("socket = %ld (!invalid socket = bon)\n", socket_perso);
    
    char ip[16];
    printf("ip ?\n");
    fgets(ip, 16, stdin);
    
    SOCKADDR_IN info_source;
                info_source.sin_family = AF_INET;
                info_source.sin_addr.s_addr = inet_addr(ip);
                info_source.sin_port = htons(80);
    connecter(&info_source, socket_perso);
    
    DWORD ThreadId;
    HANDLE h1;
    h1 = CreateThread(NULL,0,recevoir, &socket_perso, 0, &ThreadId);
    
    
    envoyer(socket_perso);
    
    fermeture(socket_perso);
    
    system("pause");
    TerminateThread(h1,0);
    system("pause");
    return 0;
    }
    
    
    
    void wsa_start()
    {
    int erreur;
    WSADATA initialisation_win32;
    erreur=WSAStartup(MAKEWORD(2,2),&initialisation_win32);
    if(erreur != 0)
    {printf("wsa_startup echouée\n");}
    else
    {printf("wsa_startup : OK\n");}
    }
    
    void connecter(SOCKADDR_IN *info_source, SOCKET socket)
    {
    int erreur = connect(socket, (struct sockaddr*)info_source, sizeof(*info_source));
    if(erreur != 0)
    {printf("connection echouée %d\n",WSAGetLastError());
    //exit(0);
    }
    else
    {printf("connection : OK\n");}
    }
    
    void envoyer(SOCKET socket)
    {
    int erreur;
    char message [1500];
    fgets(message, 1500, stdin);
    erreur = send(socket, message, strlen(message), 0);
    if(erreur == 0)
    {printf("envoie echoué\n");}
    else
    {printf("envoie OK\n");}
    }
    
    int fermeture(SOCKET socket_perso)
    {
    int err_cleanup, erreur_s, erreur_c, erreur;
    erreur_s = shutdown(socket_perso, 2);
    erreur_c = closesocket(socket_perso);
    err_cleanup=WSACleanup();
    if(erreur_s == 0 && erreur_c == 0 && err_cleanup == 0)
    			{erreur = 0;
    			return erreur;}
    else 
    	 		{erreur = 1;
    			return erreur;}
    }
    
    unsigned long WINAPI recevoir(void* socket)
    {
    SOCKET* sock = socket;
    
    char buffer[1024], ancien_buffer[1024];
    FILE* conv =fopen("conv.txt","w");
    	while(strstr(buffer,"esc") ==0)
    	{
    		recv(*sock, buffer, sizeof(buffer), 0);
    		if(strcmp(buffer, ancien_buffer)== 0)
    		{fprintf(conv, buffer);
            strcpy(ancien_buffer,buffer);}
    		printf("salut \n");//pour voir si çamarche
    		sleep(500);
    	}
    fclose(conv);
    	return 0;
    }
    le thread est tout à la fin.
    je ne voit pas ce qui peut buguer étant donné que si je met le code du thread dans le main en remplacant sock par socket_perso ça marche parfaitement.

    marci d'avance
    hedi07
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Que veux-tu faire ?

    *tu démarres un processus en \\ qui est recevoir
    *tu envoies des données sur un socket ,ferme le socket
    *Puis tu fermes le processus après une pause

    c'est normal que le thread recevoir() ne recoive rien car il est arrêté quelques instructions après

    Note:
    On n'utilise jamais TerminateThread un thread s'arrête de lui-même
    Pour boucler et savoir si c'est terminé on utilise WaitForSingleObject
    Remarks
    TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating.

    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:

    If the target thread owns a critical section, the critical section will not be released.
    If the target thread is allocating memory from the heap, the heap lock will not be released.
    If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
    If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

    Ceci serait + approprié peut-être , à tester
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    h1 = CreateThread(NULL,0,recevoir, &socket_perso, 0, &ThreadId);
    envoyer(socket_perso);
    WaitForSingleObject(recevoir,INFINITE);
    fermeture(socket_perso);
    
    system("pause");
    //TerminateThread(h1,0); NE pas utiliser sauf si on dépasse un timeout
    system("pause");
    return 0;
    Utiliser au besoin des messages avec WM_USER et PostMessage

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    c'est vrai j'ai oublier de dire ce que j'en faisait.
    mon thread est là juste pour m'entrainer à les utiliser, en fait le fichier serveur attend le message que j'envoie via envoyer() puis envoie 100 message (de "salut0" à "salut99") puis il envoie "esc" pour dire que c'est fini.

    normarlement la socket devrait recevoir dans le thread qui est en // pour ne pas bloquer le main devrait attendre jusque a terminatethread ou jusqu'à "esc".(le terminatethread n'est normalement pas utiliser puisque il devrait recevoir ce esc et arreter la fonction).

    je sais que le serveur envoie les donnée car j'ai réussi a les obtenir en mettant le recv dans le main.

    merci de ton aide
    hedi07

    edit: j'ai remi le TerminateThread car sinon le programme ne finit pas.
    et euh.... c'est quoi WM_user et PostMessage

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    1. Tu utilises TerminateThread(), c'est très mauvais.
    2. Comme indiqué dans la doc de CreateThread(), il faut utiliser _beginthreadex() à la place si tu utilises la C Run-Time Library (CRT). Et comme tu l'utilises à donf' (fopen(), etc), tu dois utiliser _beginthreadex().
    3. PostMessage() ne servira à rien ici comme tu n'as pas de fenêtre, et PostThreadMessage() non plus.
      Par contre, dans ton thread, tu pourrais utiliser select() sur le socket, ainsi tu aurais un timeout sur la réception. Alors, tu pourras ordonner au thread de se terminer, par exemple avec une variable globale déclarée volatile ou un truc plus compliqué comme un Event (créé avec CreateEvent())...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    Tu utilises TerminateThread(), c'est très mauvais.
    je sais mais comme il ne s'arretait pas je l'ai mis.

    par exemple avec une variable globale déclarée volatile ou un truc plus compliqué comme un Event (créé avec CreateEvent())...

    euh...oui tu pourra m'expliquer ce qu'est la variable globale volatil stp.

    il faut utiliser _beginthreadex() à la place si tu utilises la C Run-Time Library (CRT). Et comme tu l'utilises à donf' (fopen(), etc), tu dois utiliser _beginthreadex().
    Apres moults essai sa marche avec _beginthreadex!!(même pas warning) enfin le salut s'affiche et la boucle tourne (preuve grace au "salut") mais toujours rien en reception, en plus j'ai enlevé le terminatethread en mettant un compteur dans ma boucle.
    voici mon nouveau code de thread:
    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
    unsigned __stdcall recevoir(void* socket)
    {
    SOCKET* sock = socket;
    
    char buffer[1024], ancien_buffer[1024];
    FILE* conv =fopen("conv.txt","w");
    int i =0, j =sizeof(buffer);;
    	while(strstr(buffer,"esc") ==0 && i<102)
    	{
    	    
    		memset(buffer, 'a', 28);
    		recv(*sock, buffer, sizeof(buffer), 0);
    		if(strcmp(buffer, ancien_buffer)!= 0)
    		{fprintf(conv, buffer);
            strcpy(ancien_buffer,buffer);}
    		printf("salut \n");//pour voir si çamarche
    		sleep(50);
    		i++;
    	}
    fclose(conv);
    	return 0;
    }
    au passage j'ai memsetter le buffer au cas ou et cette fois dans le fichier il y a bien les 28 "a" mais seulement 4 ou 5 fois(alors que sa devrai etre 100 fois).

    je me pose quand même une question: comment sa se fait que recv n'est pas bloquante?

    et voici le code d'appel du thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned ThreadId;
    HANDLE h1;
    h1 = (HANDLE)_beginthreadex(NULL, 0, &recevoir, &socket_perso, 0, &ThreadId);
    (c'est quasiment le copier coller de la doc).

    salut
    hedi07

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    volatile est un motclé qui permet de dire qu'une variable peut être modifiée par un autre thread.
    Cela empêche l'optimiseur de se dire "tiens, puisqu'elle n'est pas modifiée par le code, on ne la lit qu'une fois, au lieu de la regarder en permanence".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    OK merci pour le volatile.

    mais ma fonction ne reçoit toujours pas les messages (bien que le "salut s'affiche").

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    personne ne sais?
    sa m'etonnerait sur un si bon forum!

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    re-salut a tous,

    après pas mal d'essai et quelque jour de réflexion passive (j'y pensais plus), j'ai trouvé quelque chose qui pourrait peut être m'aider: si la socket passé était une "copie" de la socket utilisé, ou si elle je passait juste la socket mais sans qu'elle soit connecter. J'ai pensé a ça mais c'est bien joli, je ne vois pas comment le vérifier.

    quelqu'un sait comment vérifier si une socket est connecter, et si il y a moyen de vérifier que les deux socket n'en sont en fait qu'une seul ?

    merci d'avance
    hedi07

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Sous Windows, le type SOCKET n'est qu'un HANDLE, l'équivalent d'un descripteur de fichier ouvert.
    Donc, si tu fais un truc de ce genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SOCKET s1 = socket( /* ... */ );
    SOCKET s2 = s1;
    Il n'y a qu'un seul socket.

    Donc, si ta fonction connecter() connecte bien le socket, le thread aura le même socket, toujours connecté.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    OK alors me revoila au point de départ,

    personne ne sais pourquoi ma fonction recevoir ne marche pas ? alors que le thread est acitf et a les bonnes données pour marcher.

    salut

    hedi07

  12. #12
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par hedi07
    OK alors me revoila au point de départ,

    personne ne sais pourquoi ma fonction recevoir ne marche pas ? alors que le thread est acitf et a les bonnes données pour marcher.
    Tu as modifié ton code ? Tu en es où ?
    Pas de Wi-Fi à la maison : CPL

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 28
    Points : 20
    Points
    20
    Par défaut
    toujours au même point, je n'ai rien pu modifier.
    le salut s'affiche toujours mais rien du coté de la réception.

    j'ai peut etre un indice ou peut etre rien mais j'ai essayer sur un vieux millenium, et le salur ne s'affichait que s'il y avait un evenement ( appuie sur une touche) et la tout les salut qui aurait du apparaitre, sont affichés.

    c'est tout ce que je sais.

    salut
    hedi07

Discussions similaires

  1. création d'un threads sous windows
    Par levaron dans le forum Threads & Processus
    Réponses: 5
    Dernier message: 09/06/2009, 11h35
  2. [Parallèle] Création d'un thread, sous windows.
    Par z980x dans le forum Threads & Processus
    Réponses: 1
    Dernier message: 11/11/2008, 12h44
  3. [Freezes] Python+Threads sous Windows
    Par gslongo dans le forum GTK+ avec Python
    Réponses: 6
    Dernier message: 24/06/2008, 21h12
  4. [C] Thread sous windows
    Par ben78 dans le forum Windows
    Réponses: 1
    Dernier message: 07/12/2007, 23h54
  5. Threads sous Windows
    Par Geoff-sk8 dans le forum Windows
    Réponses: 2
    Dernier message: 23/10/2006, 10h23

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