Windows Sockets: określanie kolejności bajtówWindows Sockets: Byte Ordering

Ten artykuł i dwa artykuły towarzyszące wyjaśniają kilka problemów dotyczących programowania Windows Sockets.This article and two companion articles explain several issues in Windows Sockets programming. W tym artykule omówiono porządkowanie bajtów.This article covers byte ordering. Inne problemy zostały omówione w artykułach: Windows Sockets: blokowanie i Windows Sockets: konwertowanie ciągów.The other issues are covered in the articles: Windows Sockets: Blocking and Windows Sockets: Converting Strings.

Jeśli używasz lub pochodzi z klasy CAsyncSocket, musisz samodzielnie zarządzać tymi problemami.If you use or derive from class CAsyncSocket, you will need to manage these issues yourself. Jeśli używasz lub dziedziczysz z klasy CSocket, MFC zarządza nimi.If you use or derive from class CSocket, MFC manages them for you.

określanie kolejności bajtówByte Ordering

Różne architektury maszyn czasami przechowują dane przy użyciu różnych kolejności bajtów.Different machine architectures sometimes store data using different byte orders. Na przykład maszyny oparte na architekturze Intel przechowują dane w odwrotnej kolejności komputerów Macintosh.For example, Intel-based machines store data in the reverse order of Macintosh (Motorola) machines. Kolejność bajtów Intel o nazwie "Little-Endian" jest również odwrotną kolejnością standardowego "Big-Endian" sieci.The Intel byte order, called "little-Endian," is also the reverse of the network standard "big-Endian" order. W poniższej tabeli opisano te warunki.The following table explains these terms.

Porządkowanie dużych i Little-Endianych bajtówBig- and Little-Endian Byte Ordering

określanie kolejności bajtówByte ordering ZnaczenieMeaning
Big-EndianBig-Endian Najbardziej znaczący bajt jest z lewej strony wyrazu.The most significant byte is on the left end of a word.
Little-EndianLittle-Endian Najbardziej znaczący bajt znajduje się po prawej stronie wyrazu.The most significant byte is on the right end of a word.

Zazwyczaj nie trzeba martwić się o konwersję kolejności bajtów dla danych wysyłanych i odbieranych przez sieć, ale istnieją sytuacje, w których należy przekonwertować zamówienia bajtów.Typically, you do not have to worry about byte-order conversion for data that you send and receive over the network, but there are situations in which you must convert byte orders.

Gdy konieczne jest przekonwertowanie zamówień bajtówWhen You Must Convert Byte Orders

Należy przekonwertować kolejność bajtów w następujących sytuacjach:You need to convert byte orders in the following situations:

  • Przekazujesz informacje, które należy interpretować przez sieć, w przeciwieństwie do danych wysyłanych na inny komputer.You are passing information that needs to be interpreted by the network, as opposed to the data you are sending to another machine. Można na przykład przekazać porty i adresy, które Sieć musi zrozumieć.For example, you might pass ports and addresses, which the network must understand.

  • Aplikacja serwera, z którą komunikujesz się, nie jest aplikacją MFC (i nie masz dla niej kodu źródłowego).The server application with which you are communicating is not an MFC application (and you do not have source code for it). To wywołuje konwersje kolejności bajtów, jeśli dwie komputery nie mają tej samej kolejności bajtów.This calls for byte order conversions if the two machines do not share the same byte ordering.

Gdy nie musisz konwertować kolejności bajtówWhen You Do Not Have to Convert Byte Orders

Można uniknąć wykonywania konwersji kolejności bajtów w następujących sytuacjach:You can avoid the work of converting byte orders in the following situations:

  • Komputery na obu końcach mogą wyrazić zgodę na nie zamienić bajtów, a oba komputery używają tego samego kolejności bajtów.The machines on both ends can agree not to swap bytes, and both machines use the same byte order.

  • Serwer, z którym nawiązujesz połączenie, jest aplikacją MFC.The server you are communicating with is an MFC application.

  • Masz kod źródłowy dla serwera, z którym nawiązujesz połączenie, aby można było jawnie określić, czy należy przekonwertować zamówienia bajtów.You have source code for the server you're communicating with, so you can tell explicitly whether you must convert byte orders or not.

  • Serwer można przenieść do biblioteki MFC.You can port the server to MFC. Jest to dość proste, a wynikiem jest zazwyczaj mniejszy, szybszy kod.This is fairly easy to do, and the result is usually smaller, faster code.

Pracując z CAsyncSocket, musisz samodzielnie zarządzać wszelkimi niezbędnymi konwersjami kolejności bajtów.Working with CAsyncSocket, you must manage any necessary byte-order conversions yourself. Windows Sockets ma ustandaryzowany model kolejności bajtów "Big-Endian" i oferuje funkcje do konwersji między tą kolejnością i innymi.Windows Sockets standardizes the "big-Endian" byte-order model and provides functions to convert between this order and others. CArchive, jednak używany z CSocket, używa przeciwległej kolejności ("Little-Endian"), ale należy CArchive pamiętać o szczegółach konwersji kolejności bajtów.CArchive, however, which you use with CSocket, uses the opposite ("little-Endian") order, but CArchive takes care of the details of byte-order conversions for you. Używając tej standardowej kolejności w aplikacjach lub korzystając z funkcji konwersji kolejności bajtów Windows Sockets, można sprawić, że kod będzie bardziej przenośny.By using this standard ordering in your applications, or using Windows Sockets byte-order conversion functions, you can make your code more portable.

Idealnym przypadkiem korzystania z funkcji MFC Sockets jest zapisanie obu punktów końcowych komunikacji: przy użyciu MFC w obu końcach.The ideal case for using MFC sockets is when you are writing both ends of the communication: using MFC at both ends. Jeśli piszesz aplikację, która będzie komunikować się z aplikacjami nienależącymi do MFC, takimi jak serwer FTP, prawdopodobnie trzeba będzie zarządzać zamienianiem bajtów samodzielnie przed przekazaniem danych do obiektu archiwum przy użyciu procedur konwersji Windows Sockets ntohs, ntohl, htons i htonl.If you are writing an application that will communicate with non-MFC applications, such as an FTP server, you will probably need to manage byte-swapping yourself before you pass data to the archive object, using the Windows Sockets conversion routines ntohs, ntohl, htons, and htonl. Przykład tych funkcji używanych podczas komunikacji z aplikacją niebędącą MFC jest wyświetlany w dalszej części tego artykułu.An example of these functions used in communicating with a non-MFC application appears later in this article.

Uwaga

Gdy inne zakończenie komunikacji nie jest aplikacją MFC, należy również unikać przesyłania strumieniowego obiektów C++ pochodzących z CObject do archiwum, ponieważ odbiornik nie będzie mógł ich obsłużyć.When the other end of the communication is not an MFC application, you also must avoid streaming C++ objects derived from CObject into your archive because the receiver will not be able to handle them. Zapoznaj się z uwagą w systemie Windows Sockets: używanie gniazd z archiwami.See the note in Windows Sockets: Using Sockets with Archives.

Aby uzyskać więcej informacji na temat zamówień bajtów, zobacz specyfikację Windows Sockets dostępną w Windows SDK.For more information about byte orders, see the Windows Sockets specification, available in the Windows SDK.

Przykład konwersji Byte-OrderA Byte-Order Conversion Example

Poniższy przykład pokazuje funkcję serializacji dla CSocket obiektu, który używa archiwum.The following example shows a serialization function for a CSocket object that uses an archive. Ilustruje także użycie funkcji konwersji kolejności bajtów w interfejsie API Windows Sockets.It also illustrates using the byte-order conversion functions in the Windows Sockets API.

W tym przykładzie przedstawiono scenariusz, w którym piszesz klienta, który komunikuje się z aplikacją serwera innej niż MFC, dla której nie masz dostępu do kodu źródłowego.This example presents a scenario in which you are writing a client that communicates with a non-MFC server application for which you have no access to the source code. W tym scenariuszu należy założyć, że serwer inny niż MFC używa standardowej kolejności bajtów sieciowych.In this scenario, you must assume that the non-MFC server uses standard network byte order. W przeciwieństwie do aplikacji klienckiej MFC używa CArchive obiektu z CSocket obiektem i CArchive używa kolejności bajtów "Little-Endian", przeciwieństwem standardu sieci.In contrast, your MFC client application uses a CArchive object with a CSocket object, and CArchive uses "little-Endian" byte order, the opposite of the network standard.

Załóżmy, że serwer spoza MFC, z którym planujesz się komunikować, ma ustanowiony protokół dla pakietu komunikatów, podobny do następującego:Suppose the non-MFC server with which you plan to communicate has an established protocol for a message packet like the following:

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

W terminologii MFC można ją wyrazić w następujący sposób:In MFC terms, this would be expressed as follows:

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

   void Serialize(CArchive &ar);
};

W języku C++, struct jest zasadniczo taka sama jak Klasa.In C++, a struct is essentially the same thing as a class. MessageStruktura może mieć funkcje członkowskie, takie jak Serialize funkcja członkowska zadeklarowana powyżej.The Message structure can have member functions, such as the Serialize member function declared above. SerializeFunkcja członkowska może wyglądać następująco:The Serialize member function might look like this:

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

Ten przykład wywołuje konwersję kolejności bajtów danych, ponieważ istnieje wyraźna niezgodność między kolejnością bajtów aplikacji serwera innego niż MFC na jednym końcu i CArchive używanej w aplikacji klienckiej MFC na drugim końcu.This example calls for byte-order conversions of data because there is a clear mismatch between the byte ordering of the non-MFC server application on one end and the CArchive used in your MFC client application on the other end. Przykład ilustruje kilka funkcji konwersji kolejności bajtów dostarczanych przez gniazda Windows Sockets.The example illustrates several of the byte-order conversion functions that Windows Sockets supplies. W poniższej tabeli opisano te funkcje.The following table describes these functions.

Funkcje konwersji Byte-Order Windows SocketsWindows Sockets Byte-Order Conversion Functions

FunkcjaFunction PrzeznaczeniePurpose
ntohsntohs Przekonwertuj liczbę 16-bitową z kolejności bajtów sieciowych na hostowanie kolejności bajtów (big-endian do little-endian).Convert a 16-bit quantity from network byte order to host byte order (big-Endian to little-Endian).
ntohlntohl Przekonwertuj liczbę 32-bitową z kolejności bajtów sieciowych na hostowanie kolejności bajtów (big-endian do little-endian).Convert a 32-bit quantity from network byte order to host byte order (big-Endian to little-Endian).
HtonsHtons Przekonwertuj liczbę 16-bitową z kolejności bajtów hosta na kolejność bajtów sieci (little-endian do big-endian).Convert a 16-bit quantity from host byte order to network byte order (little-Endian to big-Endian).
HtonlHtonl Przekonwertuj liczbę 32-bitową z kolejności bajtów hosta na kolejność bajtów sieci (little-endian do big-endian).Convert a 32-bit quantity from host byte order to network byte order (little-Endian to big-Endian).

Innym punktem tego przykładu jest to, że gdy aplikacja gniazda na drugiej stronie komunikacji nie jest aplikacją MFC, należy unikać wykonywania następujących czynności:Another point of this example is that when the socket application on the other end of the communication is a non-MFC application, you must avoid doing something like the following:

ar << pMsg;

gdzie pMsg jest wskaźnikiem do obiektu języka C++ pochodnego od klasy CObject .where pMsg is a pointer to a C++ object derived from class CObject. Spowoduje to wysłanie dodatkowych informacji MFC skojarzonych z obiektami, które nie będą zrozumiałe dla serwera, ponieważ będzie to miało zastosowanie do aplikacji MFC.This will send extra MFC information associated with objects and the server will not understand it, as it would if it were an MFC application.

Aby uzyskać więcej informacji, zobacz:For more information, see:

Zobacz teżSee also

Windows Sockets w MFCWindows Sockets in MFC