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 :

récupération Json d'une socket


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    novembre 2018
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur intégration

    Informations forums :
    Inscription : novembre 2018
    Messages : 33
    Points : 26
    Points
    26
    Par défaut récupération Json d'une socket
    Bonjour,
    J'ai crée un serveur qui reçoit des messages d'alarme.
    Mon code fonctionne correctement et je peux visualiser dans la console mon message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    if ((read_size = recv(sock , client_message , sizeof client_message - 1 , MSG_WAITALL)) < 0) 
    	{
        perror("recv()");
    	}
     
    client_message[read_size] = '\0';
    printf("taille  %d\n", read_size);
    printf("message %s\n", client_message);
    et voici un exemple du message recu
    POST / HTTP/1.1
    Content-Type: multipart/form-data; boundary=boundary
    Host: 192.168.1.100
    Connection: close
    Content-Length: 648042

    --boundary
    Content-Disposition: form-data; name="alarmResult"
    Content-Type: application/json
    Content-Length: 3368

    {
    "ipAddress": "192.168.1.64",
    "portNo": 8080,
    "protocol": "HTTP",
    "macAddress": "58:50:ed:5b:69:dc",
    "channelID": 1,
    "dateTime": "2020-12-13T06:59:25+08:00",
    "activePostCount": 1,
    "isDataRetransmission": false,
    "eventState": "active",
    "channelName": "Camera 01",
    "eventType": "alarmResult",
    "eventDescription": "alarmResult"
    }
    Je souhaiterai extraire les valeurs du json ex: ipAddress
    J'ai donc utilisé json-c et modifié mon 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
     
    	if ((read_size = recv(sock , client_message , sizeof client_message - 1 , MSG_WAITALL)) < 0)
    	{
        perror("recv()");
    	}
     
    client_message[read_size] = '\0';
    printf("taille  %d\n", read_size);
    printf("message %s\n", client_message);
     
    struct json_object *obj = json_tokener_parse(client_message);
    struct json_object *json;
     
    json_object_object_get_ex(obj, "ipAddress", &json);
    printf("ipAddress : %s\n", json_object_get_string(json));
    Malheureusement ipAddress me renvoie toujours NULL
    Merci pour votre aide

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 810
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 810
    Points : 24 174
    Points
    24 174
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Je connais pas json-c mais intuitivement je dirais que json_tokenet_parse() doit commencer son analyse à la première accolade. Or toi tu lui envoies tout le flux reçu et donc y compris l'en-tête POST/HTTP qui n'est pas du json.
    Essaye de l'appeler ainsi: struct json_object *obj = json_tokener_parse(strchr(client_message, '{'));...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    novembre 2018
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur intégration

    Informations forums :
    Inscription : novembre 2018
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    Bonjour,
    Merci pour la réponse, effectivement cela fonctionne je n'arrive pas à comprendre comment j'ai pu passer à coté de cela. Merci encore

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 810
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 810
    Points : 24 174
    Points
    24 174
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tduverger Voir le message
    effectivement cela fonctionne
    Maintenant que le test a validé l'hypothèse, à moins que la fonction json_tokener_parse() sache gérer le cas où elle reçoit NULL, je conseillerais pour être un peu plus propre de tester si strchr() a bien trouvé une accolade avant de continuer. Sauf si t'es certain à 102% d'avoir une accolade dans la string reçue de la socket.
    Donc un truc style
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *pt;
    if ((pt=strchr(client_message, '{')) == NULL) {
    	... (gestion du cas "pas d'accolade")...
    }
     
    struct json_object *obj = json_tokener_parse(pt);
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  5. #5
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 792
    Points : 8 490
    Points
    8 490
    Par défaut
    1 solution 1 peu + propre utiliser la bibliothèque cURL

    L'exemple getinmemory.c permet de stocker dans 1 structure les données qui arrivent (<- je n'ai pas testé mais je pense que tu as juste la réponse)

    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
    114
    115
    116
    /***************************************************************************
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ \| |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
     *                             \___|\___/|_| \_\_____|
     *
     * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
     *
     * This software is licensed as described in the file COPYING, which
     * you should have received as part of this distribution. The terms
     * are also available at https://curl.se/docs/copyright.html.
     *
     * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     * copies of the Software, and permit persons to whom the Software is
     * furnished to do so, under the terms of the COPYING file.
     *
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
     *
     ***************************************************************************/ 
    /* <DESC>
     * Shows how the write callback function can be used to download data into a
     * chunk of memory instead of storing it in a file.
     * </DESC>
     */ 
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include <curl/curl.h>
     
    struct MemoryStruct {
      char *memory;
      size_t size;
    };
     
    static size_t
    WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
      size_t realsize = size * nmemb;
      struct MemoryStruct *mem = (struct MemoryStruct *)userp;
     
      char *ptr = realloc(mem->memory, mem->size + realsize + 1);
      if(ptr == NULL) {
        /* out of memory! */ 
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
      }
     
      mem->memory = ptr;
      memcpy(&(mem->memory[mem->size]), contents, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
     
      return realsize;
    }
     
    int main(void)
    {
      CURL *curl_handle;
      CURLcode res;
     
      struct MemoryStruct chunk;
     
      chunk.memory = malloc(1);  /* will be grown as needed by the realloc above */ 
      chunk.size = 0;    /* no data at this point */ 
     
      curl_global_init(CURL_GLOBAL_ALL);
     
      /* init the curl session */ 
      curl_handle = curl_easy_init();
     
      /* specify URL to get */ 
      curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");
     
      /* send all data to this function  */ 
      curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
     
      /* we pass our 'chunk' struct to the callback function */ 
      curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
     
      /* some servers don't like requests that are made without a user-agent
         field, so we provide one */ 
      curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
     
      /* get it! */ 
      res = curl_easy_perform(curl_handle);
     
      /* check for errors */ 
      if(res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
      }
      else {
        /*
         * Now, our chunk.memory points to a memory block that is chunk.size
         * bytes big and contains the remote file.
         *
         * Do something nice with it!
         */ 
     
        printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
      }
     
      /* cleanup curl stuff */ 
      curl_easy_cleanup(curl_handle);
     
      free(chunk.memory);
     
      /* we're done with libcurl, so clean it up */ 
      curl_global_cleanup();
     
      return 0;
    }

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    novembre 2018
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Ingénieur intégration

    Informations forums :
    Inscription : novembre 2018
    Messages : 33
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Maintenant que le test a validé l'hypothèse, à moins que la fonction json_tokener_parse() sache gérer le cas où elle reçoit NULL, je conseillerais pour être un peu plus propre de tester si strchr() a bien trouvé une accolade avant de continuer. Sauf si t'es certain à 102% d'avoir une accolade dans la string reçue de la socket.
    Donc un truc style
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *pt;
    if ((pt=strchr(client_message, '{')) == NULL) {
    	... (gestion du cas "pas d'accolade")...
    }
     
    struct json_object *obj = json_tokener_parse(pt);
    Oui la gestion des erreurs est prévue, merci

    Citation Envoyé par foetus Voir le message
    1 solution 1 peu + propre utiliser la bibliothèque cURL

    L'exemple getinmemory.c permet de stocker dans 1 structure les données qui arrivent (<- je n'ai pas testé mais je pense que tu as juste la réponse)

    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
    114
    115
    116
    /***************************************************************************
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ \| |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
     *                             \___|\___/|_| \_\_____|
     *
     * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
     *
     * This software is licensed as described in the file COPYING, which
     * you should have received as part of this distribution. The terms
     * are also available at https://curl.se/docs/copyright.html.
     *
     * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     * copies of the Software, and permit persons to whom the Software is
     * furnished to do so, under the terms of the COPYING file.
     *
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
     *
     ***************************************************************************/ 
    /* <DESC>
     * Shows how the write callback function can be used to download data into a
     * chunk of memory instead of storing it in a file.
     * </DESC>
     */ 
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #include <curl/curl.h>
     
    struct MemoryStruct {
      char *memory;
      size_t size;
    };
     
    static size_t
    WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
      size_t realsize = size * nmemb;
      struct MemoryStruct *mem = (struct MemoryStruct *)userp;
     
      char *ptr = realloc(mem->memory, mem->size + realsize + 1);
      if(ptr == NULL) {
        /* out of memory! */ 
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
      }
     
      mem->memory = ptr;
      memcpy(&(mem->memory[mem->size]), contents, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
     
      return realsize;
    }
     
    int main(void)
    {
      CURL *curl_handle;
      CURLcode res;
     
      struct MemoryStruct chunk;
     
      chunk.memory = malloc(1);  /* will be grown as needed by the realloc above */ 
      chunk.size = 0;    /* no data at this point */ 
     
      curl_global_init(CURL_GLOBAL_ALL);
     
      /* init the curl session */ 
      curl_handle = curl_easy_init();
     
      /* specify URL to get */ 
      curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");
     
      /* send all data to this function  */ 
      curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
     
      /* we pass our 'chunk' struct to the callback function */ 
      curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
     
      /* some servers don't like requests that are made without a user-agent
         field, so we provide one */ 
      curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
     
      /* get it! */ 
      res = curl_easy_perform(curl_handle);
     
      /* check for errors */ 
      if(res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
      }
      else {
        /*
         * Now, our chunk.memory points to a memory block that is chunk.size
         * bytes big and contains the remote file.
         *
         * Do something nice with it!
         */ 
     
        printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
      }
     
      /* cleanup curl stuff */ 
      curl_easy_cleanup(curl_handle);
     
      free(chunk.memory);
     
      /* we're done with libcurl, so clean it up */ 
      curl_global_cleanup();
     
      return 0;
    }
    Merci pour ta réponse, mais en tant que débutant et par curiosité, pourquoi considère tu que cela est plus propre?

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    septembre 2009
    Messages
    1 675
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : septembre 2009
    Messages : 1 675
    Points : 841
    Points
    841
    Par défaut
    Citation Envoyé par tduverger Voir le message
    Merci pour ta réponse, mais en tant que débutant et par curiosité, pourquoi considère tu que cela est plus propre?
    Ce n'est pas que c'est plus "propre", c'est juste que Curl te permettra de plus facilement gérer tes requêtes HTTP vu qu'il y a plein de fonctions intégrées (comme par exemple récupérer que le body et/ou le header de tes requêtes. On encore gérer les cookies, HTTPS, URL encoding ...).
    ... c'est moins didactique mais tu gagneras beaucoup de temps sur le dev

  8. #8
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 792
    Points : 8 490
    Points
    8 490
    Par défaut
    Citation Envoyé par tduverger Voir le message
    Merci pour ta réponse, mais en tant que débutant et par curiosité, pourquoi considère tu que cela est plus propre?
    C'est + propre parce que tu as 1 bibliothèque qui :
    • sépare l'entête du corps
    • lit l'entête et ainsi tu peux verifier la taille et le type de la réponse (entre autres)
    • détecte les problèmes
    • te donne juste le corps


    Donc voila , là tu "sautes" l'entête juste en cherchant la première accolade ouvrante '{' sans garantie à 100% que tu arrives au début du corps (et donc de tes données json)
    Et si tu commences 1 peu à parser la réponse pour bien se positionner et être sur à 100% de commencer au début, tu as des bibliothèques qui le font déjà comme cURL

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    8 810
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 8 810
    Points : 24 174
    Points
    24 174
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tduverger Voir le message
    Merci pour ta réponse, mais en tant que débutant et par curiosité, pourquoi considère tu que cela est plus propre?
    Quand il existe un truc qui fait les choses à ta place, il y a 99,7% que le truc le fasse mieux que toi. Parce que le truc est très certainement prévu pour gérer des soucis que tu ne penses même pas pouvoir arriver.
    Ici un exemple où l'auteur explique qu'à priori lire du CSV il n'y a rien de plus facile mais qui fait apparaitre ensuite tout un tas de soucis auxquels on ne pense absolument pas.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/09/2014, 21h41
  2. Récupération JSON dans une page HTML
    Par pikamo dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 10/09/2014, 18h08
  3. Réponses: 2
    Dernier message: 16/04/2014, 13h00
  4. envoyer le résultat d'une socket à un fichier json
    Par laila840 dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 05/03/2014, 17h07
  5. [C] pb de récupération de l'IP d'une socket cliente
    Par nouknouk dans le forum Réseau
    Réponses: 1
    Dernier message: 24/11/2008, 18h33

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