共用方式為


Windows Sockets:位元組順序

本文和兩個方針手冊說明了 Windows Sockets 程式設計的幾個問題。 本文涵蓋位元組排序。 文章涵蓋其他問題: Windows 通訊端:封鎖 Windows 通訊端:轉換字串

如果您使用或衍生自 CAsyncSocket 類別 ,您必須自行管理這些問題。 如果您使用或衍生自類別 CSocket,MFC 會為您管理它們。

位元組順序

不同的電腦架構有時會使用不同的位元組順序來儲存資料。 例如,以 Intel 為基礎的機器會以 Macintosh(Motorola) 機器的反向順序儲存資料。 Intel 位元組順序,稱為「小 Endian」,也是網路標準「big-Endian」順序的反向。 下表說明這些詞彙。

Big- and Little-Endian Byte Ordering

位元組順序 意義
Big-Endian 最重要的位元組位於單字的左端。
Little-Endian 最重要的位元組是在單字的右邊。

通常,您不需要擔心透過網路傳送和接收的資料位元組順序轉換,但在某些情況下,您必須轉換位元組訂單。

當您必須轉換位元組訂單時

您需要在下列情況下轉換位元組訂單:

  • 您傳遞的資訊需要由網路解譯,而不是傳送至另一部電腦的資料。 例如,您可以傳遞網路必須瞭解的埠和位址。

  • 您正在通訊的伺服器應用程式不是 MFC 應用程式(而且您沒有原始程式碼)。 如果兩部電腦未共用相同的位元組順序,這會呼叫位元組順序轉換。

當您不需要轉換位元組訂單時

在下列情況下,您可以避免轉換位元組順序的工作:

  • 兩端的機器都同意不交換位元組,而且兩部機器都使用相同的位元組順序。

  • 您與之通訊的伺服器是 MFC 應用程式。

  • 您有與伺服器通訊的原始程式碼,因此您可以明確告知您是否必須轉換位元組訂單。

  • 您可以將伺服器移植到 MFC。 這相當容易執行,而且結果通常較小、更快速的程式碼。

使用 CAsyncSocket 時,您必須自行管理任何必要的位元組順序轉換。 Windows Sockets 會將「big-Endian」位元組順序模型標準化,並提供函式來轉換此順序與其他函式。 不過,您搭配 CSocket 使用的 CArchive 會使用相反的 (「little-Endian」) 順序,但 CArchive 會為您處理位元組順序轉換的詳細資料。 藉由在應用程式中使用此標準排序,或使用 Windows Sockets 位元組順序轉換函式,您可以讓程式碼更具可攜性。

使用 MFC 通訊端的理想案例是當您撰寫通訊的兩端時:在兩端使用 MFC。 如果您要撰寫與非 MFC 應用程式通訊的應用程式,例如 FTP 伺服器,您可能需要先自行管理位元組交換,才能將資料傳遞至封存物件,使用 Windows Sockets 轉換常式 ntohs 、ntohl htons htonl 本文稍後會出現用於與非 MFC 應用程式通訊的這些函式範例。

注意

當通訊的另一端不是 MFC 應用程式時,您也必須避免將衍生自 CObject 封存的 C++ 物件串流處理,因為接收者無法處理它們。 請參閱 Windows 通訊端中的 附注:搭配封存 使用通訊端。

如需位元組訂單的詳細資訊,請參閱 Windows SDK 中提供的 Windows 通訊端規格。

位元組順序轉換範例

下列範例顯示使用封存之物件的序列化函 CSocket 式。 它也說明如何在 Windows Sockets API 中使用位元組順序轉換函式。

此範例會示範您撰寫用戶端來與無法存取原始程式碼的非 MFC 伺服器應用程式通訊的案例。 在此案例中,您必須假設非 MFC 伺服器使用標準網路位元組順序。 相反地,您的 MFC 用戶端應用程式會使用 CArchive 物件搭配 CSocket 物件,並使用 CArchive 與網路標準相反的「小結束」位元組順序。

假設您打算通訊的非 MFC 伺服器具有訊息封包的已建立通訊協定,如下所示:

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

在 MFC 詞彙中,這會以下列方式表示:

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

   void Serialize(CArchive &ar);
};

在 C++ 中, struct 基本上與類別相同。 結構 Message 可以有成員函式,例如 Serialize 上面宣告的成員函式。 成員 Serialize 函式看起來可能像這樣:

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 用戶端應用程式中使用的 位元組順序不符。 此範例說明 Windows Sockets 提供的數個位元組順序轉換函式。 下表描述這些函式。

Windows Sockets 位元組順序轉換函式

函式 目的
ntohs 將 16 位數量從網路位元組順序轉換為裝載位元組順序(big-Endian 到 little-Endian)。
ntohl 將 32 位數量從網路位元組順序轉換為裝載位元組順序(big-Endian 到 little-Endian)。
Htons 將 16 位數量從主機位元組順序轉換為網路位元組順序(小到小到大端)。
Htonl 將 32 位數量從主機位元組順序轉換為網路位元組順序(小到 Endian 到 big-Endian)。

此範例的另一個要點是,當通訊的另一端通訊端應用程式是非 MFC 應用程式時,您必須避免執行類似下列動作:

ar << pMsg;

其中 pMsg 是衍生自 類別 CObject 之 C++ 物件的指標。 這會傳送與物件相關聯的額外 MFC 資訊,而且伺服器不會瞭解它,就如同它是 MFC 應用程式一樣。

如需詳細資訊,請參閱

另請參閱

MFC 中的 Windows Sockets