Transmission binaire
2 participants
Page 1 sur 1
Transmission binaire
Bonjour, je fais référence à cette note : http://www.bien-programmer.fr/reseaux.htm#binaire
* Si je veux envoyer un entier signé, est-ce que ceci est portable, si les deux machines ont la même représentation des nombres signés (mais pas le même endianness) ? :
Transmission
réception
La seule chose que j'ai changé, c'est le type de la variable size.
* Est-ce qu'il ne faut pas remplacer '8', par CHAR_BIT ?
* Si je veux envoyer un entier de 8 octets, imaginons sur ma machine le type unsigned long long.
Je vais avoir ce warning : 'left shift count >= width of type' pour les premiers décalages en réception :
Ca me semble normal, le paramètre à gauche de '<<' est converti certainement en unsigned int (4 octets).
Est-ce que ceci est OK :
J'ai fait le cast de partout bien que ce n'est pas la peine.
Et si j'ai un signé, cette fois je change que le type au début :
* Si je veux envoyer un entier signé, est-ce que ceci est portable, si les deux machines ont la même représentation des nombres signés (mais pas le même endianness) ? :
Transmission
- Code:
signed long size = -256;
/* donnees 'taille' effectivement transmises */
unsigned char data[4];
data[0] = (size >> (3 * 8)) & 0xFF; /* MSB (3) en tete (0) */
data[1] = (size >> (2 * 8)) & 0xFF;
data[2] = (size >> (1 * 8)) & 0xFF;
data[3] = (size >> (0 * 8)) & 0xFF;
réception
- Code:
signed long size = 0;
size |= (data[0] << (3 * 8)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8)) ;
size |= (data[2] << (1 * 8)) ;
size |= (data[3] << (0 * 8)) ;
La seule chose que j'ai changé, c'est le type de la variable size.
* Est-ce qu'il ne faut pas remplacer '8', par CHAR_BIT ?
* Si je veux envoyer un entier de 8 octets, imaginons sur ma machine le type unsigned long long.
Je vais avoir ce warning : 'left shift count >= width of type' pour les premiers décalages en réception :
- Code:
unsigned long long size;
size |= (data[0] << (7 * 8)) ; /* warning */
size |= (data[1] << (6 * 8)) ; /* warning */
size |= (data[2] << (5 * 8)) ; /* warning */
size |= (data[3] << (4 * 8)) ; /* warning */
size |= (data[4] << (3 * 8)) ;
size |= (data[5] << (2 * 8)) ;
size |= (data[6] << (1 * 8)) ;
size |= (data[7] << (0 * 8)) ;
Ca me semble normal, le paramètre à gauche de '<<' est converti certainement en unsigned int (4 octets).
Est-ce que ceci est OK :
- Code:
unsigned long long size;
size |= ((unsigned long long)data[0] << (7 * 8)) ;
size |= ((unsigned long long)data[1] << (6 * 8)) ;
size |= ((unsigned long long)data[2] << (5 * 8)) ;
size |= ((unsigned long long)data[3] << (4 * 8)) ;
size |= ((unsigned long long)data[0] << (3 * 8)) ;
size |= ((unsigned long long)data[1] << (2 * 8)) ;
size |= ((unsigned long long)data[2] << (1 * 8)) ;
size |= ((unsigned long long)data[3] << (0 * 8)) ;
J'ai fait le cast de partout bien que ce n'est pas la peine.
Et si j'ai un signé, cette fois je change que le type au début :
- Code:
signed long long size;
size |= ((unsigned long long)data[0] << (7 * 8)) ;
size |= ((unsigned long long)data[1] << (6 * 8)) ;
size |= ((unsigned long long)data[2] << (5 * 8)) ;
size |= ((unsigned long long)data[3] << (4 * 8)) ;
size |= ((unsigned long long)data[0] << (3 * 8)) ;
size |= ((unsigned long long)data[1] << (2 * 8)) ;
size |= ((unsigned long long)data[2] << (1 * 8)) ;
size |= ((unsigned long long)data[3] << (0 * 8)) ;
cirdan- Messages : 5
Date d'inscription : 20/05/2009
Re: Transmission binaire
Oui, c'est le but ! Le principe est de convertir la représentation dans un format indépendant de la machine. Ce format est respecte la convention "réseau" qui est "poids fort en tête". Il doit aussi impérativement être d'une taille fixe (2, 3, 4, 6, 8 octets etc.). Tout cela est conventionnel.cirdan a écrit:Bonjour, je fais référence à cette note : http://www.bien-programmer.fr/reseaux.htm#binaire
* Si je veux envoyer un entier signé, est-ce que ceci est portable, si les deux machines ont la même représentation des nombres signés (mais pas le même endianness) ? :
Alors ici, la transmission se fait sur 4 octets. Les valeurs transmises doivent être représentables par une combinaison de bits comprise entre entre 0 et 0xFFFFFFFF.Transmission
- Code:
signed long size = -256;
/* donnees 'taille' effectivement transmises */
unsigned char data[4];
data[0] = (size >> (3 * 8)) & 0xFF; /* MSB (3) en tete (0) */
data[1] = (size >> (2 * 8)) & 0xFF;
data[2] = (size >> (1 * 8)) & 0xFF;
data[3] = (size >> (0 * 8)) & 0xFF;
réception
- Code:
signed long size = 0;
size |= (data[0] << (3 * 8)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8)) ;
size |= (data[2] << (1 * 8)) ;
size |= (data[3] << (0 * 8)) ;
La seule chose que j'ai changé, c'est le type de la variable size.
Surtout pas. Il s'agit d'octets (format réseau) qui n'ont rien à voir avec les char de l'implémentation (c'est ça l'indépendance).* Est-ce qu'il ne faut pas remplacer '8', par CHAR_BIT ?
Exact. Il faut forcer la conversion en ull (unsigned long long) :
* Si je veux envoyer un entier de 8 octets, imaginons sur ma machine le type unsigned long long.
Je vais avoir ce warning : 'left shift count >= width of type' pour les premiers décalages en réception :
- Code:
unsigned long long size;
size |= (data[0] << (7 * 8)) ; /* warning */
size |= (data[1] << (6 * 8)) ; /* warning */
size |= (data[2] << (5 * 8)) ; /* warning */
size |= (data[3] << (4 * 8)) ; /* warning */
size |= (data[4] << (3 * 8)) ;
size |= (data[5] << (2 * 8)) ;
size |= (data[6] << (1 * 8)) ;
size |= (data[7] << (0 * 8)) ;
Ca me semble normal, le paramètre à gauche de '<<' est converti certainement en unsigned int (4 octets).
- Code:
size |= (data[0] << (7 * 8ull)) ;
etc.
Non. J'ai indiqué comment faire. D'ailleurs en toute rigueur, pour transmettre en 32-bit, on devrait faire :Est-ce que ceci est OK :
- Code:
signed long size = 0;
size |= (data[0] << (3 * 8ul)) ; /* MSB (3) en tete (0) */
size |= (data[1] << (2 * 8ul)) ;
size |= (data[2] << (1 * 8ul)) ;
size |= (data[3] << (0 * 8ul)) ;
(Obligatoire sur un compilateur 16 bit.)
Re: Transmission binaire
-ed- a écrit:Il faut forcer la conversion en ull (unsigned long long) :
- Code:
size |= (data[0] << (7 * 8ull)) ;
etc.Non. J'ai indiqué comment faire.Est-ce que ceci est OK :
Pourquoi c'est pas bon ?
Alors ici, la transmission se fait sur 4 octets. Les valeurs transmises doivent être représentables par une combinaison de bits comprise entre entre 0 et 0xFFFFFFFF.
Mais alors, c'est pas portable ?
Puisque si sizeof(long) == 8, dès que j'aurais un nombre négatif, le bit de poids le plus fort sera à 1, et la représentation binaire ne sera pas comprise entre 0 et 0xFFFFFFFF.
Non ?
cirdan- Messages : 5
Date d'inscription : 20/05/2009
Re: Transmission binaire
- Code:
unsigned long long number;
number = 0xFF << 24ull;
printf("%llx\n", number);
m'affiche : ffffffffff000000
mais
- Code:
unsigned long long number;
number = ((unsigned long long)0xFF) << 24ull;
printf("%llx\n", number);
m'affiche : ff000000
cirdan- Messages : 5
Date d'inscription : 20/05/2009
Re: Transmission binaire
Avant toute chose, il faut savoir si ton système de développement est à jour (certaines versions de Windows ne supportent pas "%llx").
Chez moi (Vista SP1 / Code::Blocks 8.02) , ce code :
Chez moi (Vista SP1 / Code::Blocks 8.02) , ce code :
- Code:
#include <stdio.h>
int main (void)
{
unsigned long long x = 0xFF;
printf ("x = %016llX\n", x << (8 * 0ull));
printf ("x = %016llX\n", x << (8 * 1ull));
printf ("x = %016llX\n", x << (8 * 2ull));
printf ("x = %016llX\n", x << (8 * 3ull));
printf ("x = %016llX\n", x << (8 * 4ull));
printf ("x = %016llX\n", x << (8 * 5ull));
printf ("x = %016llX\n", x << (8 * 6ull));
printf ("x = %016llX\n", x << (8 * 7ull));
return 0;
}
- Code:
x = 00000000000000FF
x = 000000000000FF00
x = 0000000000FF0000
x = 00000000FF000000
x = 000000FF00000000
x = 0000FF0000000000
x = 00FF000000000000
x = FF00000000000000
Process returned 0 (0x0) execution time : 0.021 s
Press any key to continue.
Re: Transmission binaire
Normal. 0xFF est un int. Il est promu en long long...cirdan a écrit:
- Code:
unsigned long long number;
number = 0xFF << 24ull;
printf("%llx\n", number);
m'affiche : ffffffffff000000
Ceci fonctionne :
- Code:
#include <stdio.h>
int main (void)
{
unsigned long long number;
number = 0xFFu << 24ull;
printf("%llx\n", number);
return 0;
}
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum