Windows Sockets: Bytereihenfolge

In diesem Artikel und zwei Begleitartikeln werden mehrere Probleme bei der Programmierung von Windows Sockets erläutert. In diesem Artikel wird die Bytebestellung behandelt. Die anderen Probleme werden in den Artikeln behandelt: Windows Sockets: Blockierung und Windows Sockets: Konvertieren von Zeichenfolgen.

Wenn Sie die Klasse CAsyncSocket verwenden oder von dieser ableiten, müssen Sie diese Probleme selbst verwalten. Wenn Sie die Klasse CSocket verwenden oder ableiten, verwaltet MFC sie für Sie.

Bytereihenfolge

Unterschiedliche Computerarchitekturen speichern manchmal Daten mit unterschiedlichen Bytereihenfolgen. Intel-basierte Computer speichern z. B. Daten in umgekehrter Reihenfolge von Macintosh-Computern (Macintosh). Die Intel-Byte-Reihenfolge, die als "little-Endian" bezeichnet wird, ist auch die Umgekehrte der Netzwerkstandardreihenfolge "big-Endian". In der folgenden Tabelle werden diese Begriffe erläutert.

Big- und Little-Endian Byte-Sortierung

Bytereihenfolge Bedeutung
Big-Endian Das wichtigste Byte befindet sich am linken Ende eines Worts.
Little-Endian Das wichtigste Byte befindet sich am rechten Ende eines Worts.

In der Regel müssen Sie sich keine Gedanken über die Bytereihenfolgekonvertierung für Daten machen, die Sie über das Netzwerk senden und empfangen, aber es gibt Situationen, in denen Sie Bytebestellungen konvertieren müssen.

Wenn Sie Bytereihenfolgen konvertieren müssen

Sie müssen Bytereihenfolgen in den folgenden Situationen konvertieren:

  • Sie übergeben Informationen, die vom Netzwerk interpretiert werden müssen, im Gegensatz zu den Daten, die Sie an einen anderen Computer senden. So können Sie beispielsweise Ports und Adressen übergeben, die das Netzwerk verstehen muss.

  • Die Serveranwendung, mit der Sie kommunizieren, ist keine MFC-Anwendung (und Sie haben keinen Quellcode dafür). Dadurch werden Bytereihenfolgenkonvertierungen aufgerufen, wenn die beiden Computer die gleiche Bytereihenfolge nicht gemeinsam nutzen.

Wenn Sie Bytereihenfolgen nicht konvertieren müssen

In den folgenden Situationen können Sie die Konvertierung von Bytereihenfolgen vermeiden:

  • Die Computer auf beiden Enden können zustimmen, bytes nicht auszutauschen, und beide Computer verwenden dieselbe Bytereihenfolge.

  • Der Server, mit dem Sie kommunizieren, ist eine MFC-Anwendung.

  • Sie verfügen über Quellcode für den Server, mit dem Sie kommunizieren, damit Sie explizit feststellen können, ob Byteaufträge konvertiert werden müssen oder nicht.

  • Sie können den Server zu MFC portieren. Dies ist relativ einfach zu erledigen, und das Ergebnis ist in der Regel kleinerer, schnellerer Code.

Wenn Sie mit CAsyncSocket arbeiten, müssen Sie alle erforderlichen Bytereihenfolge-Konvertierungen selbst verwalten. Windows Sockets standardisiert das "big-Endian"-Bytereihenfolgemodell und stellt Funktionen bereit, die zwischen dieser Reihenfolge und anderen konvertiert werden können. CArchive, die Sie jedoch mit CSocket verwenden, verwendet die entgegengesetzte ("little-Endian") Reihenfolge, kümmert sich jedoch CArchive um die Details der Bytereihenfolge-Konvertierungen für Sie. Mithilfe dieser Standardreihenfolge in Ihren Anwendungen oder mithilfe von Konvertierungsfunktionen für Windows Sockets-Bytereihenfolge können Sie Ihren Code portierbarer gestalten.

Das ideale Argument für die Verwendung von MFC-Sockets ist, wenn Sie beide Enden der Kommunikation schreiben und dabei eine MFC-Bibliothek an beiden Enden verwenden. Wenn Sie eine Anwendung schreiben, die mit Nicht-MFC-Anwendungen wie einem FTP-Server kommuniziert, müssen Sie wahrscheinlich byte-swapping selbst verwalten, bevor Sie Daten an das Archivobjekt übergeben, indem Sie die Windows Sockets-Konvertierungsroutinen "ntohs", "ntohl", "htons" und "htonl" verwenden. Ein Beispiel für diese Funktionen, die bei der Kommunikation mit einer Nicht-MFC-Anwendung verwendet werden, wird weiter unten in diesem Artikel angezeigt.

Hinweis

Wenn das andere Ende der Kommunikation keine MFC-Anwendung ist, müssen Sie auch verhindern, dass C++-Objekte, die aus CObject Ihrem Archiv abgeleitet werden, gestreamt werden, da der Empfänger sie nicht verarbeiten kann. Siehe die Notiz in Windows Sockets: Verwenden von Sockets mit Archiven.

Weitere Informationen zu Bytebestellungen finden Sie in der Windows Sockets-Spezifikation, die im Windows SDK verfügbar ist.

Beispiel für eine Bytereihenfolgekonvertierung

Das folgende Beispiel zeigt eine Serialisierungsfunktion für ein CSocket Objekt, das ein Archiv verwendet. Außerdem wird die Verwendung der Bytereihenfolgekonvertierungsfunktionen in der Windows Sockets-API veranschaulicht.

In diesem Beispiel wird ein Szenario dargestellt, in dem Sie einen Client schreiben, der mit einer Nicht-MFC-Serveranwendung kommuniziert, für die Sie keinen Zugriff auf den Quellcode haben. In diesem Szenario müssen Sie davon ausgehen, dass der Nicht-MFC-Server standardmäßige Netzwerkbytereihenfolge verwendet. Im Gegensatz dazu verwendet Ihre MFC-Clientanwendung ein CArchive Objekt mit einem CSocket Objekt und CArchive verwendet die Bytereihenfolge "little-Endian", das Gegenteil des Netzwerkstandards.

Angenommen, der Nicht-MFC-Server, mit dem Sie kommunizieren möchten, verfügt über ein etabliertes Protokoll für ein Nachrichtenpaket wie die folgende:

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

In MFC-Begriffen würde dies wie folgt ausgedrückt:

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

   void Serialize(CArchive &ar);
};

In C++ ist eine struct im Wesentlichen dasselbe wie eine Klasse. Die Message Struktur kann Memberfunktionen aufweisen, z. B. die Serialize oben deklarierte Memberfunktion. Die Serialize Memberfunktion sieht möglicherweise wie folgt aus:

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);
   }
}

In diesem Beispiel werden Bytereihenfolgekonvertierungen von Daten aufgerufen, da eine eindeutige Übereinstimmung zwischen der Bytereihenfolge der Nicht-MFC-Serveranwendung auf einem Ende und der CArchive verwendung in Ihrer MFC-Clientanwendung am anderen Ende besteht. Das Beispiel veranschaulicht mehrere der Bytereihenfolgenkonvertierungsfunktionen, die Windows Sockets bereitstellt. In der folgenden Tabelle werden diese Funktionen beschrieben.

Konvertierungsfunktionen für Windows Sockets Bytereihenfolge

Funktion Zweck
ntohs Konvertieren Sie eine 16-Bit-Menge aus der Netzwerkbytereihenfolge in die Bytereihenfolge (big-Endian in little-Endian).
ntohl Konvertieren Sie eine 32-Bit-Menge aus der Netzwerkbytereihenfolge in die Bytereihenfolge (big-Endian in little-Endian).
Htons Konvertieren Sie eine 16-Bit-Menge von der Hostbytereihenfolge in die Netzwerkbytereihenfolge (little-Endian in big-Endian).
Htonl Konvertieren Sie eine 32-Bit-Menge von der Hostbytereihenfolge in die Netzwerkbytereihenfolge (little-Endian in big-Endian).

Ein weiterer Punkt in diesem Beispiel: Wenn die Socketanwendung am anderen Ende der Kommunikation eine Nicht-MFC-Anwendung ist, müssen Sie vermeiden, etwas wie die folgenden zu tun:

ar << pMsg;

dabei pMsg handelt es sich um einen Zeiger auf ein von der Klasse CObjectabgeleitetes C++-Objekt. Dadurch werden zusätzliche MFC-Informationen gesendet, die Objekten zugeordnet sind, und der Server versteht sie nicht, wie es wäre, wenn es sich um eine MFC-Anwendung handelt.

Weitere Informationen finden Sie unter:

Siehe auch

Windows-Sockets in MFC