程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Windows Sockets:字節排序

Windows Sockets:字節排序

編輯:關於C語言

本文以及另外兩篇相關文章解釋 Windows Sockets 編程方面的一些問題。本文介紹字節排序。其他問題在文章 Windows Sockets:阻塞Windows Sockets:轉換字符串中介紹。

如果使用 CAsyncSocket 類或從其派生,則您需要自己管理這些問題。如果您使用 CSocket 類或從其派生,則由 MFC

管理它們。

字節排序

不同的計算機結構有時使用不同的字節順序存儲數據。例如,基於 Intel 的計算機存儲數據的順序與 Macintosh

(Motorola) 計算機相反。Intel 字節順序稱為“Little-Endian”,與網絡標准“Big-Endian”順序也相反。下表解

釋這些術語。

Big-Endian 和 Little-Endian 字節排序

字節排序 含義 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 Sockets:使用帶存檔的套接字中的說明。

有關字節順序的更多信息,請參見 Platform SDK 中的 Windows Sockets 規范。

字節順序轉換示例

下面的示例顯示使用存檔的 CSocket 對象的一個序列化函數。它還闡釋了在 Windows Sockets API 中如何使用

字節順序轉換函數。

該示例顯示這樣的情形:您正在編寫與非 MFC 服務器應用程序通信的客戶程序,而您沒有訪問該服務器應用程序

源代碼的權限。在這種情況下,必須假設非 MFC 服務器使用標准的網絡字節順序。相反,MFC 客戶端應用程序對

CSocket 對象使用 CArchive 對象,而 CArchive 使用與網絡標准相反的“Little-Endian”字節順序。

假設要與之通信的非 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 服務器應用程序的字節排序與另一端在 MFC 客戶端應用程序中使用的 CArchive 明顯不匹配。該示例闡釋了 Windows Sockets 提供的幾個字節順序轉換函數。下表描述了這些函數。

Windows Sockets 字節順序轉換函數

函數 作用 ntohs 將 16 位數量從網絡字節順序轉換為主機字節順序(從 Big-Endian 轉換為 Little-Endian)。 ntohl 將 32 位數量從網絡字節順序轉換為主機字節順序(從 Big-Endian 轉換為 Little-Endian)。 htons 將 16 位數量從主機字節順序轉換為網絡字節順序(從 Little-Endian 轉換為 Big-Endian)。 htonl 將 32 位數量從主機字節順序轉換為網絡字節順序(從 Little-Endian 轉換為 Big-Endian)。

此示例的另一個要點是,當通信另一端的套接字應用程序為非 MFC 應用程序時,必須避免出現如下列語句的操作:

ar pMsg; 

這裡的 pMsg 是指向從 CObject 類派生的 C++ 對象的指針。這將發送多余的與對象關聯的 MFC 信息,而服務器並不理解這些信息,因為只有服務器是 MFC 應用程序時才理解。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved