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

Résolu
nostalgius Messages postés 18 Date d'inscription mercredi 28 janvier 2009 Statut Membre Dernière intervention 22 juillet 2011 - 5 juin 2010 à 01:56
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 ::
A voir également:

7 réponses

TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
5 juin 2010 à 10:32
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é.
3
nostalgius Messages postés 18 Date d'inscription mercredi 28 janvier 2009 Statut Membre Dernière intervention 22 juillet 2011
5 juin 2010 à 11:59
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
0
nostalgius Messages postés 18 Date d'inscription mercredi 28 janvier 2009 Statut Membre Dernière intervention 22 juillet 2011
5 juin 2010 à 12:08
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;
}
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
5 juin 2010 à 14:52
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);
}
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
5 juin 2010 à 14:55
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)
  /* ... */
0
nostalgius Messages postés 18 Date d'inscription mercredi 28 janvier 2009 Statut Membre Dernière intervention 22 juillet 2011
24 juin 2010 à 11:07
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
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
24 juin 2010 à 11:28
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
0
Rejoignez-nous