Windows ソケット : バイトの順序付けWindows Sockets: Byte Ordering

この記事と2つの記事では、Windows ソケットプログラミングにおけるいくつかの問題について説明します。This article and two companion articles explain several issues in Windows Sockets programming. この記事では、バイトの順序付けについて説明します。This article covers byte ordering. その他の問題については、「 Windows ソケット: ブロッキングWindows ソケット: 文字列の変換」の記事で説明されています。The other issues are covered in the articles: Windows Sockets: Blocking and Windows Sockets: Converting Strings.

CAsyncSocketクラスを使用する場合、またはクラスを派生させる場合は、これらの問題を自分で管理する必要があります。If you use or derive from class CAsyncSocket, you will need to manage these issues yourself. またはを使用する場合は、 MFC でそれらを管理します。If you use or derive from class CSocket, MFC manages them for you.

バイトの順序付けByte Ordering

異なるコンピューターアーキテクチャでは、異なるバイトオーダーを使用してデータを格納する場合があります。Different machine architectures sometimes store data using different byte orders. たとえば、Intel ベースのコンピューターでは、Macintosh (Motorola) コンピューターの逆の順序でデータが保存されます。For example, Intel-based machines store data in the reverse order of Macintosh (Motorola) machines. "リトルエンディアン" と呼ばれる Intel のバイトオーダーも、ネットワークの標準の "ビッグエンディアン" の順序と逆になります。The Intel byte order, called "little-Endian," is also the reverse of the network standard "big-Endian" order. 次の表では、これらの用語について説明します。The following table explains these terms.

ビッグエンディアンのバイト順Big- and Little-Endian Byte Ordering

バイトの順序付けByte ordering 意味Meaning
ビッグエンディアンBig-Endian 最上位バイトは単語の左端にあります。The most significant byte is on the left end of a word.
リトルエンディアンLittle-Endian 最上位バイトは単語の右端にあります。The most significant byte is on the right end of a word.

通常、ネットワーク経由で送受信されるデータのバイトオーダーの変換について心配する必要はありませんが、バイトオーダーを変換する必要がある場合があります。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.

バイトオーダーを変換する必要がある場合When You Must Convert Byte Orders

次の状況では、バイトオーダーを変換する必要があります。You need to convert byte orders in the following situations:

  • 別のコンピューターに送信するデータではなく、ネットワークによって解釈される必要がある情報を渡しています。You are passing information that needs to be interpreted by the network, as opposed to the data you are sending to another machine. たとえば、ネットワークが認識する必要があるポートとアドレスを渡すことができます。For example, you might pass ports and addresses, which the network must understand.

  • 通信中のサーバーアプリケーションは、MFC アプリケーションではありません (ソースコードはありません)。The server application with which you are communicating is not an MFC application (and you do not have source code for it). 2台のコンピューターが同じバイト順序を共有していない場合、はバイト順変換を呼び出します。This calls for byte order conversions if the two machines do not share the same byte ordering.

バイトオーダーを変換する必要がない場合When You Do Not Have to Convert Byte Orders

次の状況では、バイトオーダーの変換作業を回避できます。You can avoid the work of converting byte orders in the following situations:

  • 両端のマシンは、バイトをスワップしないことに同意し、両方のコンピューターが同じバイト順を使用します。The machines on both ends can agree not to swap bytes, and both machines use the same byte order.

  • 通信しているサーバーは MFC アプリケーションです。The server you are communicating with is an MFC application.

  • 通信しているサーバーのソースコードがあるため、バイトオーダーを変換する必要があるかどうかを明示的に判断できます。You have source code for the server you're communicating with, so you can tell explicitly whether you must convert byte orders or not.

  • サーバーを MFC に移植できます。You can port the server to MFC. これは非常に簡単です。通常、結果はより小さく、より高速なコードです。This is fairly easy to do, and the result is usually smaller, faster code.

CAsyncSocketを使用する場合は、必要なバイト順変換を自分で管理する必要があります。Working with CAsyncSocket, you must manage any necessary byte-order conversions yourself. Windows ソケットは、"ビッグエンディアン" バイト順モデルを標準化し、この順序と他の順序の間で変換を行う関数を提供します。Windows Sockets standardizes the "big-Endian" byte-order model and provides functions to convert between this order and others. ただし、 CSocketで使用するCArchiveは、逆の ("リトルエンディアン") 順序を使用し CArchive ますが、バイト順変換の詳細を処理します。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. アプリケーションでこの標準の順序付けを使用するか、Windows ソケットのバイト順変換関数を使用することにより、コードの移植性を高めることができます。By using this standard ordering in your applications, or using Windows Sockets byte-order conversion functions, you can make your code more portable.

MFC ソケットの理想的な使用状況は、通信の両端を自分で作成し、両端で MFC を使用する場合です。The ideal case for using MFC sockets is when you are writing both ends of the communication: using MFC at both ends. FTP サーバーなど、MFC 以外のアプリケーションと通信するアプリケーションを作成する場合は、Windows Sockets 変換ルーチンntohsntohlhtons、および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. MFC 以外のアプリケーションとの通信で使用されるこれらの関数の例については、この記事の後半で説明します。An example of these functions used in communicating with a non-MFC application appears later in this article.

注意

通信のもう一方の側が MFC アプリケーションでない場合は、から派生した C++ オブジェクトを、受信側がそれを処理できないのでアーカイブに保存しないようにする必要もあり CObject ます。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. Windows ソケット: アーカイブでのソケットの使用」の注を参照してください。See the note in Windows Sockets: Using Sockets with Archives.

バイトオーダーの詳細については、Windows SDK で使用可能な Windows ソケット仕様を参照してください。For more information about byte orders, see the Windows Sockets specification, available in the Windows SDK.

バイト順変換の例A Byte-Order Conversion Example

次の例は、アーカイブを使用するオブジェクトのシリアル化関数を示して CSocket います。The following example shows a serialization function for a CSocket object that uses an archive. また、Windows Sockets API でバイト順変換関数を使用する方法についても説明します。It also illustrates using the byte-order conversion functions in the Windows Sockets API.

この例は、ソースコードにアクセスできない非 MFC サーバーアプリケーションと通信するクライアントを作成するシナリオを示しています。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. このシナリオでは、非 MFC サーバーが標準的なネットワークのバイト順を使用することを前提としています。In this scenario, you must assume that the non-MFC server uses standard network byte order. これに対し、MFC クライアントアプリケーションでは、オブジェクトを使用してオブジェクトを使用 CArchive CSocket し、ネットワーク標準とは逆の CArchive "リトルエンディアン" バイト順を使用します。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.

通信を計画している非 MFC サーバーが、次のようなメッセージパケットに対して確立されたプロトコルを持っているとします。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;
};

MFC の用語では、これは次のように表されます。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);
};

C++ では、は基本的には struct クラスと同じです。In C++, a struct is essentially the same thing as a class. 構造体には、 Message 上で宣言されたメンバー関数などのメンバー関数を含めることができ Serialize ます。The Message structure can have member functions, such as the Serialize member function declared above. Serializeメンバー関数は次のようになります。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);
   }
}

この例では、データのバイト順変換に対してを呼び出しています。これは、一方の端にある非 MFC サーバーアプリケーションのバイト順と、もう一方の側の CArchive mfc クライアントアプリケーションで使用されるが明確に一致しないためです。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. この例は、Windows ソケットが提供するバイト順変換関数のいくつかを示しています。The example illustrates several of the byte-order conversion functions that Windows Sockets supplies. 次の表では、これらの関数について説明します。The following table describes these functions.

Windows ソケットのバイト順変換関数Windows Sockets Byte-Order Conversion Functions

機能Function 目的Purpose
ntohsntohs 16ビットの数量をネットワークのバイト順からホストのバイト順 (ビッグエンディアンからリトルエンディアン) に変換します。Convert a 16-bit quantity from network byte order to host byte order (big-Endian to little-Endian).
ntohlntohl 32ビットの数量をネットワークのバイト順からホストのバイト順 (ビッグエンディアンからリトルエンディアン) に変換します。Convert a 32-bit quantity from network byte order to host byte order (big-Endian to little-Endian).
HtonsHtons 16ビットの数量をホストのバイト順からネットワークのバイト順 (リトルエンディアンからビッグエンディアン) に変換します。Convert a 16-bit quantity from host byte order to network byte order (little-Endian to big-Endian).
HtonlHtonl 32ビットの数量をホストのバイト順からネットワークのバイト順 (リトルエンディアンからビッグエンディアン) に変換します。Convert a 32-bit quantity from host byte order to network byte order (little-Endian to big-Endian).

この例のもう1つの点は、通信の相手側のソケットアプリケーションが非 MFC アプリケーションである場合、次のような処理を避ける必要があることです。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;

ここ pMsg で、はクラスから派生した C++ オブジェクトへのポインターです CObjectwhere pMsg is a pointer to a C++ object derived from class CObject. これにより、オブジェクトに関連付けられている追加の MFC 情報が送信されます。これは、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.

詳細については、次を参照してください。For more information, see:

関連項目See also

MFC における Windows ソケットWindows Sockets in MFC