Partager via


Windows Sockets : classement des octets

Cet article et deux autres articles similaires décrivent plusieurs problèmes de programmation Windows Sockets. Cet article traite de l’ordre d’octets. Les autres problèmes sont abordés dans les articles : Windows Sockets : Blocage et Sockets Windows : Conversion de chaînes.

Si vous utilisez ou dérivez de la classe CAsyncSocket, vous devez gérer vous-même ces problèmes. Si vous utilisez ou dérivez de la classe CSocket, MFC les gère pour vous.

Classement des octets

Différentes architectures de machine stockent parfois des données à l’aide de commandes d’octets différentes. Par exemple, les machines Intel stockent les données dans l’ordre inverse des machines Macintosh (Motorola). L’ordre d’octets Intel, appelé « little-Endian », est également l’inverse de l’ordre « big-Endian » standard du réseau. Le tableau suivant décrit ces termes.

Classement d’octets big-and-little-endian

Classement des octets Signification
Big-Endian L’octet le plus significatif se trouve à gauche d’un mot.
Little-Endian L’octet le plus significatif se trouve à droite d’un mot.

En règle générale, vous n’avez pas à vous soucier de la conversion d’ordre d’octet pour les données que vous envoyez et recevez sur le réseau, mais il existe des situations dans lesquelles vous devez convertir des commandes d’octets.

Lorsque vous devez convertir des commandes d’octets

Vous devez convertir des commandes d’octets dans les situations suivantes :

  • Vous transmettez des informations qui doivent être interprétées par le réseau, par opposition aux données que vous envoyez à un autre ordinateur. Par exemple, vous pouvez passer des ports et des adresses, que le réseau doit comprendre.

  • L’application serveur avec laquelle vous communiquez n’est pas une application MFC (et vous n’avez pas de code source pour celui-ci). Cela appelle les conversions d’ordre d’octets si les deux machines ne partagent pas le même ordre d’octets.

Lorsque vous n’avez pas besoin de convertir les commandes d’octets

Vous pouvez éviter le travail de conversion des commandes d’octets dans les situations suivantes :

  • Les machines des deux extrémités peuvent accepter de ne pas échanger d’octets, et les deux machines utilisent le même ordre d’octet.

  • Le serveur avec lequel vous communiquez est une application MFC.

  • Vous disposez d’un code source pour le serveur avec lequel vous communiquez. Vous pouvez donc indiquer explicitement si vous devez convertir des commandes d’octets ou non.

  • Vous pouvez porter le serveur vers MFC. Cela est assez facile à faire, et le résultat est généralement plus petit, plus rapide code.

Avec CAsyncSocket, vous devez gérer vous-même les conversions d’ordre d’octets nécessaires. Windows Sockets standardise le modèle d’ordre d’octet « big-Endian » et fournit des fonctions pour effectuer une conversion entre cet ordre et d’autres. CArchive, cependant, que vous utilisez avec CSocket, utilise l’ordre opposé (« little-Endian »), mais CArchive prend en charge les détails des conversions d’ordre d’octets pour vous. En utilisant cet ordre standard dans vos applications ou à l’aide de fonctions de conversion d’octets Windows Sockets, vous pouvez rendre votre code plus portable.

Le cas idéal pour l’utilisation de sockets MFC est lorsque vous écrivez les deux extrémités de la communication : l’utilisation de MFC aux deux extrémités. Si vous écrivez une application qui communiquera avec des applications non MFC, telles qu’un serveur FTP, vous devrez probablement gérer vous-même l’échange d’octets avant de passer des données à l’objet archive, à l’aide des routines de conversion Windows Sockets ntohs, ntohl, htons et htonl. Un exemple de ces fonctions utilisées pour communiquer avec une application non MFC apparaît plus loin dans cet article.

Remarque

Lorsque l’autre extrémité de la communication n’est pas une application MFC, vous devez également éviter de diffuser en continu des objets C++ dérivés de CObject votre archive, car le récepteur ne pourra pas les gérer. Consultez la note dans Windows Sockets : Utilisation de sockets avec archives.

Pour plus d’informations sur les commandes d’octets, consultez la spécification windows Sockets, disponible dans le Kit de développement logiciel (SDK) Windows.

Exemple de conversion d’ordre d’octets

L’exemple suivant montre une fonction de sérialisation pour un CSocket objet qui utilise une archive. Il illustre également l’utilisation des fonctions de conversion d’ordre d’octet dans l’API Windows Sockets.

Cet exemple présente un scénario dans lequel vous écrivez un client qui communique avec une application serveur non MFC pour laquelle vous n’avez pas accès au code source. Dans ce scénario, vous devez supposer que le serveur non-MFC utilise l’ordre d’octet réseau standard. En revanche, votre application cliente MFC utilise un CArchive objet avec un objet et CArchive utilise l’ordre CSocket d’octet « little-Endian », l’opposé de la norme réseau.

Supposons que le serveur non-MFC avec lequel vous envisagez de communiquer a un protocole établi pour un paquet de messages comme suit :

struct Message
{
   long MagicNumber;
   unsigned short Command;
   short Param1;
   long Param2;
};

En termes MFC, cela serait exprimé comme suit :

struct Message
{
   long m_lMagicNumber;
   short m_nCommand;
   short m_nParam1;
   long m_lParam2;

   void Serialize(CArchive &ar);
};

En C++, il struct s’agit essentiellement de la même chose qu’une classe. La Message structure peut avoir des fonctions membres, telles que la Serialize fonction membre déclarée ci-dessus. La Serialize fonction membre peut ressembler à ceci :

void Message::Serialize(CArchive &ar)
{
   if (ar.IsStoring())
   {
      ar << (DWORD)htonl(m_lMagicNumber);
      ar << (WORD)htons(m_nCommand);
      ar << (WORD)htons(m_nParam1);
      ar << (DWORD)htonl(m_lParam2);
   }
   else
   {
      WORD w;
      DWORD dw;
      ar >> dw;
      m_lMagicNumber = ntohl((long)dw);
      ar >> w;
      m_nCommand = ntohs((short)w);
      ar >> w;
      m_nParam1 = ntohs((short)w);
      ar >> dw;
      m_lParam2 = ntohl((long)dw);
   }
}

Cet exemple appelle des conversions d’ordre d’octets de données, car il existe une incompatibilité claire entre l’ordre d’octets de l’application serveur non-MFC à une extrémité et celle CArchive utilisée dans votre application cliente MFC à l’autre extrémité. L’exemple illustre plusieurs fonctions de conversion d’ordre d’octet que Windows Sockets fournit. Le tableau suivant décrit ces fonctions.

Fonctions de conversion d’ordre d’octets Windows Sockets

Fonction Objectif
ntohs Convertissez une quantité de 16 bits de l’ordre d’octet réseau en ordre d’octet hôte (big-Endian en little-Endian).
ntohl Convertissez une quantité 32 bits de l’ordre d’octet réseau en ordre d’octet hôte (big-Endian en little-Endian).
Htons Convertissez une quantité 16 bits de l’ordre d’octet de l’hôte en ordre d’octet réseau (little-Endian en big-Endian).
Htonl Convertissez une quantité 32 bits de l’ordre d’octet de l’hôte en ordre d’octet réseau (little-Endian en big-Endian).

Un autre point de cet exemple est que lorsque l’application de socket sur l’autre extrémité de la communication est une application non MFC, vous devez éviter de faire quelque chose comme suit :

ar << pMsg;

pMsg est un pointeur vers un objet C++ dérivé de la classe CObject. Cela envoie des informations MFC supplémentaires associées à des objets et le serveur ne le comprend pas, comme il le ferait s’il s’agissait d’une application MFC.

Pour en savoir plus, consultez :

Voir aussi

Windows Sockets dans MFC