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

C++ Discussion :

Socket et protocole UDP, ne lire que la dernière donnée reçue


Sujet :

C++

  1. #1
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut Socket et protocole UDP, ne lire que la dernière donnée reçue
    Bonjour,

    j'ai une classe qui me permet de lire les données UDP d'un PC client :
    Code c++ : 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
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
     
    #include <iostream>
    #include <cstring>
    #include "SocketClass.h"
     
     
    using namespace std;
     
    SocketClass::SocketClass(int port)
    {
        this->port = port;
        this->socketError = NO_ERROR;
    	this->sec = 5;
    	this->usec = 0;
    }
     
    SocketClass::~SocketClass()
    {
    	if (socketError == NO_ERROR)
    	{
    		socketError = shutdown(socketServer, SD_BOTH);
    		socketError = closesocket(socketServer);
    	}
     
    	WSACleanup();
    }
     
    /**
    Initialisation du socket
    **/
    int SocketClass::initSocket()
    {
        WSADATA WSAData;
     
        socketError = WSAStartup(MAKEWORD(2,2), &WSAData);    // initialisation du socket, utilisation de la verions 2.0 de winsock
        if (socketError!=NO_ERROR)
        {
            return socketError;
        }
     
        // initialisation du socket
        sin.sin_addr.s_addr	= htonl(INADDR_ANY);    // pas d'adresse, mode serveur
        sin.sin_family		= AF_INET;              // protocole IPv4
        sin.sin_port		= htons(port);          // port
     
     
        // création du socket
        socketServer = socket(AF_INET, SOCK_DGRAM, 0);
     
        if (socketServer == INVALID_SOCKET)
        {
            socketError = INVALID_SOCKET;
            //WSACleanup();
            return INVALID_SOCKET;
        }
     
     
    	// bind
        socketError = bind(socketServer, (SOCKADDR *)&sin, sizeof(sin));
        if (socketError == SOCKET_ERROR)
        {
            //WSACleanup();
            return SOCKET_ERROR;
        }
     
    	// taille du buffer de lecture
        socketError = setsockopt(socketServer, SOL_SOCKET, SO_RCVBUF, (char*)&data, sizeof(data));
        if (socketError == SOCKET_ERROR)
        {
           // WSACleanup();
            return SOCKET_ERROR;
        }
     
    	socketError = NO_ERROR;
        return NO_ERROR;
    }
     
    /**
    Fermeture du socket
    **/
    int SocketClass::closeSocket()
    {
    	if (socketError == NO_ERROR)
    	{
    		socketError = shutdown(socketServer, SD_BOTH);
    		socketError = closesocket(socketServer);
    	}
     
    	WSACleanup();
     
        return socketError;
    }
     
    /**
    Time out sur le socket
    **/
    void SocketClass::setTimeOut(int sec, int usec)
    {
    	this->sec = sec;
    	this->usec = usec;
    }
     
     
    /**
    Lecture des données
    **/
    int SocketClass::readData()
    {
        int sinSize;
        int len;
     
        fd_set fd;
        timeval tv;
     
        sinSize = sizeof(sin);
        len = NO_ERROR;
     
    	if (socketError == NO_ERROR)
    	{
    		//while(1)
    		{
    			FD_ZERO(&fd);
    			FD_SET(socketServer, &fd);
     
    			tv.tv_sec = sec;		// timeout sur la méthode accept
    			tv.tv_usec = usec;
     
    			if (select(0, &fd, NULL, NULL, &tv) > 0)
    			{
    				len = recvfrom(socketServer, (char*)&data, sizeof(data), 0, (SOCKADDR *)&sin, &sinSize);
     
    				/*if (len > 0)
    					break;*/
    			   /* if (len == SOCKET_ERROR)
    					break;*/
    			}
    		}
    	}
     
    	//Sleep(20);
     
        return len;
    }

    Le client m'envoie les données en continue. Et mon serveur, lui ne lit les données avec la fonction readData() qui est appelée 1 fois par seconde. Je reçois donc plus de données que je n'en lis.

    Or il semblerait que les données soient stockées dans une pile FIFO et lors de la lecture du buffer je ne lis que la 1ère donnée reçue (la plus ancienne), or moi ce qui m'intéresse c'est la dernière donnée (la plus récente).
    J'ai pourtant précisé que la taille du buffer de lecture était de la taille de ma variable data.

    Comment je dois modifier mon code pour ne récupérer que la dernière donnée reçue et jeter le reste ?

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    J'ai surtout envie de te poser une autre question: pourquoi demander au client d'envoyer des données en continu si c'est pour te foutre royalement de la majorité des données envoyées

    Ne serait-il pas préférable (ne serait-ce que pour éviter de surcharger le réseau) de faire en sorte que le client n'envoie que des données qui devront quoi qu'il arrive être traitées par le serveur
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Pour répondre à la question si pour x raison tu ne peux pas suivre les bons conseils de Koala01 :

    Si c'était FIFO (First In First Out), tu lirais justement le dernier paquet reçu en premier. Donc c'est peut-être plus FILO (une pile d'assiette) que tu voulais dire. Et si c'est le cas, tu pourrais dépiler jusqu'à lire la dernière "assiette" ?

    EDIT : oh là là mais j'arrête pas de dire des conneries moi en ce moment "first in first out ... donc le dernier d'abord..."

    Oui tu as une pile (FIFO donc ^^), et donc pourquoi tu dépile pas jusqu'à lire le dernier paquet ?
    Nullius in verba

  4. #4
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    @koala01 : Malheureusement pour moi le client fonctionne comme ça. Mais c'est vrai l'idéal serait que le client m'envoie les données à la demande. Je vais quand même demander à la personne qui a programmé ce client de voir comment elle peut le modifier.

    @Kaamui :
    Si c'était FIFO (First In First Out), tu lirais justement le dernier paquet reçu en premier
    tu es sûr ? Si je reçois le paquet P(n) à t(n) et P(n+1) à t(n+1) c'est P(n) qui sort en premier dans une pile FIFO pas P(n+1).


    Sinon dans le cas où la modification du code client ne serait pas possible est-ce qu'il y a un moyen de procéder ? J'ai pensé à un thread qui est chargé de lire port en permanence et une fonction getData() qui me retourne une donnée à un temps t.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    FIFO = file d'attente, premier arrivé, premier servi
    LIFO = pile, dernier arrivé, premier servi
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    J'ai créé un thread pour lire les données entrantes :
    Code c++ : 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
     
    DWORD SocketClass::readDataFrom()
    {
    	int sinSize;
     
        fd_set fd;
        timeval tv;
     
    	static HANDLE l_hsProtect = CreateSemaphore(NULL,1,1,NULL);
    	WaitForSingleObject(l_hsProtect, INFINITE);
     
        sinSize = sizeof(sin);
        dataLen = 0;
    	dataReadLen = 0;
     
    	if (socketError == NO_ERROR)
    	{
    		while(!stopReading)
    		{
    			FD_ZERO(&fd);
    			FD_SET(socketServer, &fd);
     
    			tv.tv_sec = sec;		// timeout sur la méthode accept
    			tv.tv_usec = usec;
     
    			if (select(0, &fd, NULL, NULL, &tv) > 0)
    			{
    				dataLen = recvfrom(socketServer, (char*)&data, sizeof(data), 0, (SOCKADDR *)&sin, &sinSize);
    				if (memData)
    				{
    					dataReadLen = dataLen;
    					dataRead.id = data.id;
    					dataRead.time = data.time;
    					dataRead.x = data.x;
    					dataRead.y = data.y;
    					dataRead.z = data.z;
    					memData = false;
    				}
    			}
    		}
    	}
     
    	dataLen = 0;
    	dataReadLen = 0;
    	memData = false;
        ReleaseSemaphore(l_hsProtect,1,NULL);
     
        return 0;
    }

    L'idée est ensuite, d'utiliser un flag memData pour mémoriser la donnée à un moment voulu. Mais comment ensuite récupérer dataRead ?
    Car je vais être confronté à un problème de synchronisation. J'ai pensé aux mutex, mais je ne vois pas comment procéder.

  7. #7
    Membre émérite
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Points : 2 274
    Points
    2 274
    Par défaut
    Salut toi
    Coucou tout le monde

    Bon, déjà, je précise que je ne connais rien pour ainsi dire au socket, mais... je relève toutefois, du moins je pense, ce qui me semble être des incohérences dans ton code par rapport au comportement que tu souhaites de celui-ci.

    À ce que je lis, ta variable de réception "data" n'est qu'un simple tableau de caractères, et ça ne se rapproche en rien d'un "container" ou d'une "pile", donc techniquement, à chaque lecture de celle-ci, t'es supposé avoir la dernière donnée reçue. Si tu lis tout le temps la même valeur, donc la première que tu reçois après chaque redémarrage de ton serveur, c'est que tu lis juste la première valeur stockée par ta classe, mais je crois qu'elle n'est jamais mises à jour. En d'autres termes, ça veut dire qu'après la première réception, ton serveur se ferme et n'est plus à l'écoute. Donc, outre un problème de gestion des erreurs, je pense qu'il y a une confusion et une collision entre, d'une part, le destructeur de ta classe et d'autre part, la fonction membre "closeSocket" qui en plus d'utiliser l'api "closesocket" fait aussi un WSACleanup.

    Voilà, si ça peut t'aider...

    P.-S. : si je suis à côté de la plaque, ne pas tenir compte du message
    il fallait bien que je le place mon smiley préféré

  8. #8
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Auteur Voir le message
    Car je vais être confronté à un problème de synchronisation. J'ai pensé aux mutex, mais je ne vois pas comment procéder.
    Il faut s'assurer qu'un seul thread accède à la donnée en même temps. Schématiquement ça donne
    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
    class SocketClass {
    public:
       void readData() {
           while(!stop) {
               Data d = recvfrom(...);
               {
                    // lock le mutex pour pouvoir modifier m_lastData sans qu'un autre thread n'y accède pendant ce temps
                    std::lock_guard<std::mutex> lock(m_mutexData);
                    m_lastData = d;
                    m_hasData = true;
               }
            }
         }
     
         Data getData() {
             // lock le mutex pour pouvoir copier m_lastData sans qu'il soit modifier pendant la copie
             std::lock_guard<std::mutex> lock(m_mutexData);
             m_hasData = false; // c'est assez sale de set un attribut dans un getter
                   // mais tu vois l'idée.
             return m_lastData; // return une copie
         }
     
         bool hasData() const {
             return m_hasData;
         }
     
    private:
       Data m_lastData;
       std::mutex m_mutexData;
       std::atomic<bool> m_hasData;
    };

  9. #9
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    @minnesota :
    à l'origine le fonctionnement du serveur était celui-ci (le code que j'ai posté au début) :
    1- ouverture du socket serveur
    2- lecture d'une donnée
    3- traitement de l'information (opération +/- longue)
    4- retour en 2 sinon en 5 si arrêt du serveur demandé
    5- arrêt du serveur
    data est une structure de cette forme :
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct info{
    int id;
    double x, y, z, time;}

    Comme je ne voulais pas de boucle bloquante j'ai supprimé le while(1) que l'on voit dans readData. De même, je ne fais pas de connexion /déconnexion après chaque lecture.

    Et je pensais que le recvfrom n'allait me renvoyer que la donnée reçue au moment de l'appel à cette fonction. Or ce n'est pas le cas.


    @Iradrille : je testerai ton code mais je vois déjà quelque chose qui pourrait me poser problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::atomic<bool> m_hasData;
    Je crois que le concept d'élément <atomic> est assez récent (chose que je ne connaissais pas je l'avoue ) et est complètement inconnu de Visual Studio 2010
    La librairie Boost a de quoi gérer ce genre d'élément.


    J'ai vu aussi que l'on pourrait utiliser une variable volatile mais que cela poserait des problèmes au niveau de la mémoire.

  10. #10
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Auteur Voir le message
    Je crois que le concept d'élément <atomic> est assez récent (chose que je ne connaissais pas je l'avoue ) et est complètement inconnu de Visual Studio 2010
    La librairie Boost a de quoi gérer ce genre d'élément.
    VS2010 risque de ne pas connaitre non plus std::mutex et std::lock_guard.

    Ces éléments sont présent dans Boost. (atomic / thread / mutex / lock_guard)

  11. #11
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    J'ai essayé d'utiliser le type <atomic> et les mutex de boost 1.55. Au moment de la génération du projet j'ai cette erreur :
    LINK : fatal error LNK1104: impossible d'ouvrir le fichier 'libboost_atomic-vc100-mt-s-1_55.lib'
    cela vient clairement de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <boost/atomic.hpp>
    #include <boost/thread/mutex.hpp>
    Est-ce qu'il y a un moyen de résoudre ce problème.... sans boost ?

  12. #12
    Membre émérite
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Points : 2 274
    Points
    2 274
    Par défaut
    Salut tout le monde,
    Coucou Auteur,

    Ben normalement juste avec l'API Windows tu devrais t'en sortir... les mutex sont pris en charge...

    Sinon, ton but c'est de savoir si l'ordi qui héberge l'application client est toujours en ligne ? C'est ça ?
    Ou est-ce que tu as besoin de collecter toutes les données ? Dans ce cas à quelle fréquence sont-elles envoyées ?

  13. #13
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Salut;

    j'ai commencé des tests avec L'API Windows que je reprendrai en janvier.
    Sinon : l'application client envoie les données toutes les 100ms en moyenne (cela peut être variable).

    Le serveur (mon application) lit la donnée et la traite. Ce traitement peut être assez long (+/- 1,5s) par rapport à la période d'envoi. Je ne veux pas traiter les données qui ont été envoyées durant le traitement car périmées, je ne veux récupérer que la dernière donnée arrivée, quand le serveur est disponible (à la fin du traitement donc).
    Je me suis aperçu que pour éliminer les données trop vieilles il faut que le serveur les dépile ou alors, la dernière possibilité reste la suivante :
    1- ouvrir le serveur ;
    2- lire 1 donnée ;
    3- fermer le serveur ;
    4- traitement de l'information reçue ;
    5- retour à l'étape 1.
    ce que je trouve un peu dommage.

  14. #14
    Membre émérite
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Points : 2 274
    Points
    2 274
    Par défaut
    Mais normalement y'a pas à "dépiler" quoi que ce soit... t'as qu'une "variable"... ton serveur est censé écraser son contenu à chaque nouvelle réception de donnée... non ?

    Réessaye en réinitialisant ta structure à 0 avant chaque écriture (std::memset ou ZeroMemory)...

  15. #15
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Ce que je voulais dire par "dépiler" : tant que je n'appelle pas recvfrom() les données reçues sont stockées (dans le buffer de la carte réseau sans aucun doute).

    Au moment de l'appel à recvfrom() je retire 1 donnée de la pile or cette donnée n'est pas la dernière arrivée, c'est la première arrivée à partir du dernier appel à recvfrom().

  16. #16
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    Bonjour,

    Comme je t'ai indiqué sur le chat, tu peux jouer avec les CriticalSection pour verouiller la lecture/écriture de ta variable.

    En gros t'aurais:
    - Un thread qui passe son temps à recv, et dès qu'il reçoit quelque chose, entre dans la CriticalSection, réécrit ton buffer avec ce qu'il a reçu puis en sortir
    - Ton application, qui en entrant dans la même CriticalSection va lire le buffer (le copier en local), sortir de la CriticalSection et traiter les données avec sa copie locale, et une fois ceci fait on recommence.

    A mon avis, c'est la manière la plus simple de faire.
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

  17. #17
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Citation Envoyé par supersnail Voir le message
    Bonjour,

    Comme je t'ai indiqué sur le chat, tu peux jouer avec les CriticalSection pour verouiller la lecture/écriture de ta variable.
    j'y travaille

  18. #18
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Attention tout de même aux mutex gérer manuellement (via l'api Win32 par exemple), si les exceptions sont mal gérées, c'est un mutex bloqué à vie !
    L'implémentation d'une classe type std::lock_guard est plus que recommandée
    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
    struct noncopyable {
    protected:
        ~noncopyable() { }
        noncopyable() { }
    private:
         noncopyable(const noncopyable&);
         noncopyable& operator=(const noncopyable&);
    };
     
    class LockGuard: noncopyable {
    public:
         explicit LockGuard(HANDLE m): mutex(m) {
             WaitForSingleObject(mutex, INFINITE);
         }
         ~LockGuard() {
              ReleaseMutex(mutex)
         }
    private:
        HANDLE mutex;
    };
    Pour les critical sections, il peut y avoir le même problème, je ne sais pas.
    Si c'est le cas, l'utilisation d'une classe similaire est utile.

  19. #19
    Membre émérite
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Points : 2 793
    Points
    2 793
    Par défaut
    Sinon j'ai vu aussi que la fonction TryEnterCriticalSection existait et ne bloquait pas le thread (la fonction renvoie juste false si on a pas réussi à rentrer dans la section critique, i.e la section critique est déjà verouillée).

    Sinon les Mutex win32 ils ne sont utiles qu'en cas de communucation inter-process (avec mémoire partagée, etc, ici ce serait sortir un tank pour écraser une mouche.
    Toute question technique envoyée en MP ira directement à la poubelle

    Un code ne marchera jamais, il n'a jamais reçu la capacité de se déplacer.
    Inutile donc de dire "ça marche pas", donnez plutôt des informations précises afin de mieux pouvoir vous aider.


    Grand gourou de la -attitude

  20. #20
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par supersnail Voir le message
    Sinon les Mutex win32 ils ne sont utiles qu'en cas de communucation inter-process (avec mémoire partagée, etc, ici ce serait sortir un tank pour écraser une mouche.
    C'est pas la joie pour les std::mutex :/
    Bon après... il y à normalement peu de lock / unlock à faire sinon c'est un problème de conception, mais quand même, bien déçu du surcout.

    Je vais regarder les sections critiques de plus près et me faire une tite classe pour les gérer comme des mutexes sur Windows et qui fallback vers un std::mutex sur un autre OS.

    TryEnterCriticalSection n'est pas utile ici, même s'il faut attendre, on veut rentrer pour récupérer la valeur ou en stocker une nouvelle.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Protocole UDP et Socket
    Par yazidi_marwen dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 10/06/2012, 15h19
  2. Socket et protocole IRC
    Par EpOnYmE187 dans le forum WinDev
    Réponses: 8
    Dernier message: 10/02/2006, 14h54
  3. Ne lire que à partir du n ième caractère
    Par dj-julio dans le forum Langage
    Réponses: 2
    Dernier message: 17/01/2006, 13h21
  4. Réponses: 10
    Dernier message: 10/01/2006, 09h12
  5. raw socket et protocole TCP/IP
    Par robertmouac dans le forum Développement
    Réponses: 3
    Dernier message: 09/03/2005, 23h09

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