Problème envoi chaine binaire: send() s'arrête sur le premier '\0' rencontré [Résolu]

Messages postés
18
Date d'inscription
mercredi 28 janvier 2009
Statut
Membre
Dernière intervention
22 juillet 2011
- - Dernière réponse : TychoBrahe
Messages postés
1309
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
- 24 juin 2010 à 11:28
Salut tout le monde..
Là je tente d'envoyer une image (simple exemple) avec send(), une image étant un fichier binaire elle contient des caractère non-imprimable tel que le '\0' (caractère nul) et là mon send() s'arrête sur le premier '\0' rencontré.
quelqu'un a une solution ?
(à part recourir à un encodage base64 ou quelque chose de semblable).

Merci d'avance.

:: un simple curieux ::
Afficher la suite 

7 réponses

Meilleure réponse
Messages postés
1309
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
11
3
Merci
Salut,

Je serai curieux de voir ton code, en particulier la manière donc tu calcules la longueur de la chaîne à envoyer. Si tu utilises un strlen() pour calculer cette longueur alors il est parfaitement normal que ça s'arrête au premier \0 rencontré.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 190 internautes nous ont dit merci ce mois-ci

Commenter la réponse de TychoBrahe
Messages postés
18
Date d'inscription
mercredi 28 janvier 2009
Statut
Membre
Dernière intervention
22 juillet 2011
0
Merci
Merci!! en faite j'utilisai strlen() pour spécifier la taille des données à envoyer, là je donne comme paramètre la taille de mon fichier et ça marche!!
Merci encore

Voici ma fonction envoi_fichier, si vous avez des remarques pour
Commenter la réponse de nostalgius
Messages postés
18
Date d'inscription
mercredi 28 janvier 2009
Statut
Membre
Dernière intervention
22 juillet 2011
0
Merci
Merci!! en faite j'utilisai strlen() pour spécifier la taille des données à envoyer, là je donne comme paramètre la taille de mon fichier et ça marche!!
Merci encore

Voici ma fonction envoi_fichier, si vous avez des remarques pour l'améliorer:

int envoi_fichier(SOCKET sur_socket, char* fichier)
{
    FILE *p_fichier;

    p_fichier = fopen(fichier, "rb");
        if (p_fichier == NULL) return 0;
            puts("\n\touverture fichier source");
            int longueur = 0;
            while (!feof(p_fichier))
            {
                fgetc(p_fichier);
                longueur++;
            }
    fclose(p_fichier);

    printf("\n\ttaille fichier: %d", longueur);
    unsigned char* contenu_fichier;
    contenu_fichier = malloc(longueur*sizeof(char));
    puts("\n\tinitialisation conteneur");
    int i;
    for(i=0; i<longueur+1; i++) contenu_fichier[i]= '\0';

    p_fichier = fopen(fichier, "rb");
        if (p_fichier == NULL) return 0;
        i=0;
        while (!feof(p_fichier))
        {
            contenu_fichier[i] = fgetc(p_fichier);
            i++;
        }
    fclose(p_fichier);

    char t_donnees_a_envoyer[10] = {0};
    sprintf(t_donnees_a_envoyer, "%d", longueur);
    if(send(sur_socket, t_donnees_a_envoyer, strlen(t_donnees_a_envoyer), 0) == SOCKET_ERROR) return 0;
    if(send(sur_socket, &t_donnees_a_envoyer[strlen(t_donnees_a_envoyer)+1], 1, 0) == SOCKET_ERROR) return 0;
    if(send(sur_socket, contenu_fichier, longueur ,0) == SOCKET_ERROR) return 0;

    free(contenu_fichier);
    return 1;
}
Commenter la réponse de nostalgius
Messages postés
1309
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
11
0
Merci
Merci encore

De rien ;)

si vous avez des remarques pour l'améliorer

Oui, mapper le fichier en mémoire est bien plus efficace. A noter que mmap() n'existe aps sous windows, il temfaudra regarder les différentes documentation pour trouver un équivalent (j'ai connais un pour le C++ sous windows mais pas pour le C).

Un exemple d'implémentation sur un système GNU/Linux :
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include 
#include <stdio.h>
#include <fcntl.h>

int             send_file(int so, const char *file)
{
  struct stat   st;
  int           fd;
  int           nbw;
  char          *addr;

  fd = open(file, O_RDONLY);
  if (fd == -1)
    {
      perror("open");
      return -1;
    }
  fstat(fd, &st);
  addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (addr == MAP_FAILED)
    {
      perror("mmap");
      return -1;
    }
  nbw = send(so, addr, st.st_size, 0);
  if (nbw != st.st_size)
    {
      perror("send");
      munmap(addr, st.st_size);
      return -1;
    }
  return munmap(addr, st.st_size);
}
Commenter la réponse de TychoBrahe
Messages postés
1309
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
11
0
Merci
Errata: j'ai oublié le close() (à ajouter juste après le mmap().

Avec les lignes précédentes et suivantes ça donne :
  /* ... */
  addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  close(fd);
  if (addr == MAP_FAILED)
  /* ... */
Commenter la réponse de TychoBrahe
Messages postés
18
Date d'inscription
mercredi 28 janvier 2009
Statut
Membre
Dernière intervention
22 juillet 2011
0
Merci
Re TychoBrahe.
Désolé pour mon retard. je suis un peu débordé ces derniers temps .
Je vais essayer de trouver une équivalente sous Windows. en attendant ça consiste en quoi "mapper le fichier en mémoire"
Dslé encore et Merciii
Commenter la réponse de nostalgius
Messages postés
1309
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
11
0
Merci
Salut,

en attendant ça consiste en quoi "mapper le fichier en mémoire"

Tout simplement à le charger dans la mémoire afin d'y avoir directement accès. Bref, tu récupère un pointeur vers un espace mémoire contenant le fichier. Pour caricaturer, c'est un peu comme un gros malloc dans lequel on copie le fichier. La différence la plus notable est que mmap est bien plus "intelligent" (optimisation de l'utilisation réel de la mémoire etc).

Quelques liens :
mmap() sur Wikipedia
man 2 mmap
Commenter la réponse de TychoBrahe