Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här artikeln och två kompletterande artiklar förklarar flera problem i Windows Sockets-programmering. Den här artikeln beskriver byteordning. De andra problemen beskrivs i artiklarna: Windows Sockets: Blockering och Windows Sockets: Konvertera strängar.
Om du använder eller härleder från klassen CAsyncSocket måste du hantera dessa problem själv. Om du använder eller härleder från klassen CSocket, hanterar MFC dem åt dig.
Byteordning
Olika datorarkitekturer lagrar ibland data med olika bytebeställningar. Intel-baserade datorer lagrar till exempel data i omvänd ordning för Macintosh-datorer (Motorola). Intel-byteordningen, som kallas "little-Endian", är också motsatsen till nätverksstandarden "big-Endian" order. I följande tabell förklaras dessa termer.
Big- och Little-Endian byteordning
| Byteordning | Innebörd |
|---|---|
| Big-Endian | Den viktigaste byte är i den vänstra änden av ett ord. |
| Little-Endian | Det mest signifikanta byte är till höger i ett ord. |
Normalt behöver du inte bekymra dig om byteordning för data som du skickar och tar emot via nätverket, men det finns situationer där du måste konvertera byteordningar.
När du måste konvertera byteordning
Du måste konvertera bytebeställningar i följande situationer:
Du skickar information som måste tolkas av nätverket, till skillnad från de data som du skickar till en annan dator. Du kan till exempel skicka portar och adresser, vilket nätverket måste förstå.
Serverprogrammet som du kommunicerar med är inte ett MFC-program (och du har inte källkod för det). Detta kräver byteorderkonverteringar om de två datorerna inte delar samma byteordning.
När du inte behöver konvertera byteordningar
Du kan undvika arbetet med att konvertera bytebeställningar i följande situationer:
Datorerna i båda ändar kan komma överens om att inte byta byte, och båda datorerna använder samma byteordning.
Servern du kommunicerar med är ett MFC-program.
Du har källkod för den server som du kommunicerar med, så du kan uttryckligen se om du måste konvertera bytebeställningar eller inte.
Du kan porta servern till MFC. Detta är ganska enkelt att göra, och resultatet är vanligtvis mindre, snabbare kod.
När du arbetar med CAsyncSocket måste du hantera eventuella nödvändiga byteordningskonverteringar själv. Windows Sockets standardiserar byteordningsmodellen "big-Endian" och tillhandahåller funktioner för att konvertera mellan den här ordningen och andra.
CArchive, som du använder med CSocket, använder dock den motsatta ("little-Endian") ordningen, men CArchive tar hand om informationen om byte-order-konverteringar åt dig. Genom att använda den här standardordningen i dina program eller med hjälp av konverteringsfunktioner för byteordning i Windows Sockets kan du göra koden mer portabel.
Det idealiska fallet för att använda MFC-socketer är när du skriver båda ändarna av kommunikationen och använder MFC i båda ändar. Om du skriver ett program som kommunicerar med icke-MFC-program, till exempel en FTP-server, måste du förmodligen hantera bytebyteväxling själv innan du skickar data till arkivobjektet med hjälp av Windows Sockets-konverteringsrutinerna ntohs, ntohl, htons och htonl. Ett exempel på dessa funktioner som används för att kommunicera med ett icke-MFC-program visas senare i den här artikeln.
Anmärkning
När den andra änden av kommunikationen inte är ett MFC-program måste du också undvika strömmande C++-objekt som härletts från CObject till ditt arkiv eftersom mottagaren inte kommer att kunna hantera dem. Se anteckningen i Windows Sockets: Using Sockets with Archives (Använda socketar med arkiv).
Mer information om bytebeställningar finns i Windows Sockets-specifikationen, som är tillgänglig i Windows SDK.
Ett Byte-Order konverteringsexempel
I följande exempel visas en serialiseringsfunktion för ett CSocket objekt som använder ett arkiv. Den visar också hur du använder konverteringsfunktionerna för byteordning i Windows Sockets-API:et.
I det här exemplet visas ett scenario där du skriver en klient som kommunicerar med ett icke-MFC-serverprogram som du inte har åtkomst till källkoden för. I det här scenariot måste du anta att icke-MFC servern använder standard-nätverksbyteordning. Däremot använder MFC-klientprogrammet ett CArchive objekt med ett CSocket objekt och CArchive använder "little-Endian" byteordning, motsatsen till nätverksstandarden.
Anta att den icke-MFC-server som du planerar att kommunicera med har ett etablerat protokoll för ett meddelandepaket som liknar följande:
struct Message
{
long MagicNumber;
unsigned short Command;
short Param1;
long Param2;
};
I MFC-termer skulle detta uttryckas på följande sätt:
struct Message
{
long m_lMagicNumber;
short m_nCommand;
short m_nParam1;
long m_lParam2;
void Serialize(CArchive &ar);
};
I C++, är en struct i stort sett samma sak som en klass. Strukturen Message kan ha medlemsfunktioner, till exempel medlemsfunktionen Serialize som deklareras ovan. Medlemsfunktionen Serialize kan se ut så här:
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);
}
}
I det här exemplet anropas byteordningskonverteringar av data eftersom det finns ett tydligt matchningsfel mellan byteordningen för det icke-MFC-serverprogrammet i ena änden och det CArchive som används i MFC-klientprogrammet i den andra änden. Exemplet illustrerar flera av de konverteringsfunktioner för byteordning som Windows Sockets tillhandahåller. I följande tabell beskrivs dessa funktioner.
Konverteringsfunktioner för Windows Sockets Byte-Order
| Funktion | Avsikt |
|---|---|
| ntohs | Konvertera en 16-bitars kvantitet från nätverksbyteordningen till värd för byteordning (big-Endian till little-Endian). |
| ntohl | Konvertera en 32-bitars kvantitet från nätverksbyteordning till värdbyteordning (Big-endian till Little-endian). |
| Htons | Konvertera en 16-bitars kvantitet från värdbyteordning till nätverksbyteordning (little-Endian till big-Endian). |
| Htonl | Konvertera en 32-bitars kvantitet från värdbyteordning till nätverksbyteordning (little-Endian till big-Endian). |
En annan punkt i det här exemplet är att när socket-programmet i andra änden av kommunikationen är ett icke-MFC-program måste du undvika att göra något som liknar följande:
ar << pMsg;
där pMsg är en pekare till ett C++-objekt som härletts från klassen CObject. Detta skickar extra MFC-information som är associerad med objekt och servern kommer inte att förstå det, som om det vore ett MFC-program.
Mer information finns i: