Windows Sockets:字节排序
发布时间:2006-05-05 19:03:28 来源:MSDN 网友评论 0 条本文以及另外两篇相关文章解释 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 应用程序时才理解。
- 推荐阅讯
- C++箴言:为类型信息使用特征类
- C++ Builder2006控件的安装方法
- VC编程轻松获取局域网连接通知
- 解析Cookie欺骗实现过程及具体应用
- 在MFC下如何定义全局变量和全局函数
- 最常见的20种VC++编译错误信息
- VC编程中如何操作数据库中的图像字段
- C++中理解“传递参数”和异常之间的差异
- c++友元的入门教程
- C++数据类型的属性与限制
- 阅读排行
- 1.Borland 发布C++ Builder 2006 RAD 环境
- 2.C/C++程序员应聘常见面试题深入剖析
- 3.Visual C++常用数据类型转换详解
- 4.C++中的 static 关键字
- 5.利用VC++实现局域网实时视频传输
- 6.浅谈C/C++内存泄漏及其检测工具
- 7.英国投票否决C++/CLI 微软强攻ISO标准受挫
- 8.VC++下用MSComm控件实现串口通讯
- 9.伪随机数生成及在VC++中的实现
- 10.VC++编程实现对波形数据的频谱分析
- 专题教程
- Windows Server-Windows Server文档-Windows Server新闻-Windows Ser PostgreSQL-PostgreSQL文档-PostgreSQL新闻-PostgreSQL专家
- WebLogic-WebLogic文档-WebLogic新闻-WebLogic专家 FreeBSD-FreeBSD文档-FreeBSD新闻-FreeBSD专家
- Linux-内核 GUI KDE Gnome DNS FTP 安全 安装-Linux专区 Windows-AD IIS ServerCore 虚拟化 安全 HPC-Windows专区
- 大话G游 专题:手机病毒揭密
- ARP攻击防范与解决方案 路由故障处理手册
