网络编程/在哪些场景中不必要进行网络字节序装换? Windows Sockets: Byte Ordering

文章目录

  • 概述
  • 字节序
  • 必须转换字节序的的情况
  • 不必转换字节序的的情况
  • 字节序转换的例程
  • 字节序转换函数
  • 字节序转换可以不生硬
  • 字节序和位序

概述

本文主要讲述了在哪些场景下必须要进行大小端字节序转换,在哪些场景下可以不用进行大小端字节序转换,IP和端口号转网络字节序的必要性、避免应用数据逐个字段生硬转字节序的方法。在 MSDN Windows Sockets: Byte Ordering 帮助文档案例的基础上,略微延伸,以对网络字节序应用场景、主机字节序与网络字节序结构定义和转换方法,形成更直观些的认识。

@History
对于大部分猿,很少会碰到真正需要字节序转换的场景,相关官方资料也并不多。偶然在MSDN中发现了, Windows Sockets: Byte Ordering 这篇文章,其讲述的是 Windows 套接字编程系列问题。你可以在MSDN查看器中搜索,也可以按照上述连接来跳转在线帮助页面,本文基于上述文章内容,进行了适当的展开说明,其大场景是基于 Windows Sockets 的,还掺杂了MFC的宣教,多少带着些片面,但这并不妨碍其给我们带来期望的启迪。

转载请标明出处,
https://blog.csdn.net/quguanxin/category_10527523.html

字节序

在《存储与传输/大小端字节序的概念、决定因素、给编程带来的困扰》文章中,已经详细的描述了大小端字节序的名称的来源及其概念的记忆方法,这里不再赘述。该小节是 MSDN 中对 Intel 处理器字节序的一个简短说明。

不同的机器架构有时会使用不同的字节顺序存储数据。例如,基于 Intel 的机器使用的字节顺序与 Macintosh (Motorola) 机器相反。Intel 的字节顺序被称为"小端"(Little-Endian),也与网络标准的"大端"(Big-Endian)顺序相反。大端字节序和小端字节序的具体表述如下:
在这里插入图片描述
通常情况下,在通过网络发送和接收数据时,你不需要担心字节顺序的转换。但是,也存在一些情况下你必须进行字节顺序的转换。

在这里插入图片描述

必须转换字节序的的情况

你需要在以下情况下进行字节顺序转换:
在这里插入图片描述
1、当你需要传递一些信息,而这些信息需要被 [network] ( 网络(设备))正确解释,而不是仅仅(as opposed to )传递数据(与前半句的待传递信息对应)给另一台机器。例如,你可能需要传递端口号和地址,这些信息必须被网络设备正确理解。而此处所谓的network网络设备可能是指,路由器、交换机、防火墙、负载均衡器等,如果不进行适当的字节顺序转换,这些网络设备可能无法正确地解析和处理端口号和IP地址等信息,更直接的描述是,人家这些通用网络设备都遵循了网络字节序规则,因此你也要遵循。
我们也该注意到另一个问题,就是上述网络设备,它只能解析到端口和地址等TCP/IP头的字段,而对于应用层数据段,它们不关心也没有依据去解析数据内容。只有参与通信的终端设备才会知道数据内容的真正含义,也才有可能进行多字节数据的字节序转换。
由上述分析可以衍生出来1个小结论,网路字节序在TCP/IP层,也即在网络设备上被解析的层次上,其强制性要更高,是必须要遵守的。对应的,在应用层数据段上,这种强制性显得略弱一些,不是必须遵守的。

2、如果你正在与一个服务器应用程序通信,而该服务程序不是 MFC 应用程序(并且你没有它的源代码)。这是因为(this calls for),两台机器可能使用不同的字节序,需要进行转换以确保数据能够正确传输和解释。

也要注意的是,并不是只有涉及到网络通信时才会产生大小端的需求。一些其他的情况,如,
1、存储和传输数据: 如果你需要在不同的平台之间传输数据,并且这些平台使用不同的字节顺序,则需要进行字节顺序转换。否则,数据可能会被错误地解释。
2、跨平台编程: 当在不同架构的机器上运行程序时,如果程序需要在本地使用数据,则必须确保数据的字节顺序正确。这通常需要在读取和写入数据时进行转换。

不必转换字节序的的情况

在如下情况下,没有必要进行字节序转换。
在这里插入图片描述
1、通信双方使用相同的字节序,且已经约定好了都不进行字节序变换。
2、你正在与之通信的服务是基于MFC应用程序。不要过度解读这句话,说这句话的前提是,上下文中谈论的是windows套接字,而不是其他平台或系统,MFC 的特殊性在于它与 Windows 操作系统深度集成,可以确保字节序的一致性,从而免去了手动转换的需要。
3、你正在与之通信的服务程序,你持有它的源代码,基于此,你可以清楚明确地(explicitly)辨别出是否需要进行字节序转换。
4、您可以将服务器程序port移植到 MFC 平台上。这通常比较容易实现,而且最终得到的代码通常会更小、运行更快。感觉是套话。

接下来的这两段,与MFC太过密切,

先简单扩展下,CAsyncSocket 是 MFC 提供的一个基础的异步 Socket 类。它提供了Socket编程的基本功能,如创建、连接、收发数据等,使用 CAsyncSocket 需要自己处理字节序转换等细节。CArchive 是 MFC 的一个序列化类,用于对数据进行序列化和反序列化。它会自动处理字节序转换的细节,确保数据在不同字节序的平台间传输正确。CSocket 是建立在 CAsyncSocket 之上的一个更高级的 Socket 类。它集成了数据流读写操作,使用更加方便,其内部会使用 CArchive 类来处理字节序转换。

在使用 CAsyncSocket 时,您必须自行管理任何必要的字节顺序转换。Windows Sockets 采用了"大端"字节顺序模型作为标准,并提供了函数来在这种顺序与其他顺序之间进行转换。但是,您在使用 CSocket 时会用到 CArchive,它使用的是相反的(“小端”)顺序。不过 CArchive 会自动处理好字节顺序转换的细节。通过在您的应用程序中使用这种标准的字节顺序,或者使用 Windows Sockets 提供的字节顺序转换函数,您可以使您的代码更加可移植。

使用 MFC Sockets 的理想情况是当您正在编写通信的双方都使用 MFC 时。但是,如果您正在编写一个应用程序,它需要与非 MFC 应用程序(如 FTP 服务器)进行通信,那么在将数据传递给 Archive 对象之前,您很可能需要自己管理字节交换,使用 Windows Sockets 提供的 ntohs、ntohl、htons 和 htonl 等转换函数。本文稍后会给出一个与非 MFC 应用程序进行通信时使用这些函数的示例。当通信的另一端不是 MFC 应用程序时,您还必须避免将从 CObject 派生的 C++ 对象流式传输到您的 Archive 中,因为接收端无法处理这些对象。

字节序转换的例程

很长的一段时间内,我苦于找不到有字节序转换的实际场景,我怀着一颗无比好奇的心开始了本例程的阅读。接下来的例程,向我们展示了一个使用Archive的CSocket对象的 serialization function 序列化函数。它还向我们阐明了(illustrates )如何在Windows Socket API 中使用字节序转换函数。示例中提出presents了一个如下场景scenario,
你要写一个客户端与服务端通信,但是该服务端不是基于MFC平台的,且你不能访问到该服务端程序的源代码。在此情景下,你必须假定这个服务端程序使用的是标准网络字节序。in contrast 相比之下,您的 MFC 客户端应用程序使用了一个 CSocket 对象和一个 CArchive 对象,而 CArchive 使用 “小端” 字节顺序,这与网络标准的 “大端” 字节顺序相反。

假设你计划与之通信的服务程序,已经制定 established 了的如下所示的消息包协议,protocol for a message packet
在这里插入图片描述

你要写的基于MFC的客户端,对应的消息结构如下,

struct Message {
    long m_lMagicNumber;
    short m_nCommand;
    short m_nParam1;
    long m_lParam2;
    void Serialize( CArchive& ar );
};

在C++中,一个结构体本质上与一个类是一致的,上述Message结构可以具有一个成员函数,如上述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 提供的几个字节顺序转换函数。下表描述了这些函数:
在这里插入图片描述
英语单词 quantity 不仅具有数量、大量等意思,还有数值的意思,如上 32-bit quantity 表示一个32比特的数值。 以htonl函数为例,

//host to net long int 
u_long htonl([in] u_long hostlong);

在这里插入图片描述
如上,htonl的MSDN中提到了,使用该函数可以将一个本地字节序的IP地址转换成网络字节序的IP地址,但是不会检查作为输入参数的IP地址的合法性。字节序转换函数的使用,不依赖于WSAStart来初始化网络库。还有就是不要想多了,这是Windows网络库中的函数,这里的htonl就是完全的等价于将小端字节序转换成大端字节序,没有什么额外的其他处理。

字节序转换可以不生硬

看完上文小节中的中大小端字节序转换的例子,我不知道你想到了什么。我想到的是,如果 Message 不是只有4个待转换的多多字节字段,而是有10个,或者,还有Message2…Message50需要做类似的转换,呃呃呃,你会不会被搞得头大? 不禁要问,难道跨平台的大小端字节序转换,只能是逐个消息结构,逐个结构字段,如此生硬的进行转化? 显然那不可能!我们简单聊聊这个事情。

前文已经讨论过,在有些情况下可以不去进行字节序转换,有的时候必须要进行,这两种状态的大前提都是得有需要进行字节序转换的多字节数据。说到这里,就想到了围魏救赵解决字节序问题的一个思路,即,消除待传输信息中的多字节数据。这里的消除,可以是真正的消除,如传输结构中只使用字节数组,当然这不太现实;也可以是像文本文件加BOM的方式那样,显式的标记出传输的文件/字节流是大端还是小端字节序的。不过讲真的,好像很难回避啊?消息数据都是单字节,不靠谱。即使是文本文件,也必须要考虑多字节编码情况下的大小端问题。
如,HTTP消息是以文本形式传输的,通常使用ASCII编码或UTF-8编码。UTF-8 编码使用 1-4个字节来表示每个字符,当时多字节时,就要考虑大小端问题。我们就着文本文件编码这个事情,稍微深入下:

文本文件的字节序标记
在 MSDN 中还发现了 Using Byte Order Marks 这篇文章,一起写在这里,进一步加深对字节序的理解,并不打算具体深入展开。
始终为 Unicode 纯文本文件添加字节顺序标记的前缀(BOM),以告知接收文件的应用程序该文件的字节序。如此一来,传输此文件时,就不用关心其字节序了,由接收端按照BOM标记自行处理。必须先要理解的是,所谓文本文件,其中存储的并不是可见字符,而是字符的编码值,文本编辑器或其他应用程序替我们完成了字符编码值和可见字符之间的转换。文本文件的内容就是一串数字编码,比如ASCII编码或者Unicode编码。文本编辑器会根据文件中的编码值,查找对应的字形并显示出来。
在这里插入图片描述
如果文件编码是UTF-32,则每个文本字符都使用4个字节表示,将所有编码显示为可见字符,这很好理解。使用 UTF-32 编码可以简化一些字符处理操作,但是它占用更多的存储空间。实际应用中,UTF-8 和 UTF-16 通常是更常见和推荐的 Unicode 编码方式,如微软使用的就是UTF16 编码,小端字节序。UTF-8 编码使用 1-4个字节来表示每个字符。UTF-16 编码使用 2 个字节或 4 个字节来表示每个字符。以UFT-8为例,它是如何知道,读取到1个字节后,就可以翻译成可见字符,而不是再读取下一个字节,联合成两个字节后再一起翻译成一个可见字符?时间有限,这个放在后续发布的字符串和字符编码的博文中继续讨论和讲述。

字节序和位序

这节内容,本不该写在这里,但是写着写着就契合啦。
以太网协议规定了数据的字节传输顺序,但并没有规定数据的位传输顺序。与之不同的是,CAN协议本身并没有规定字节发送顺序,它只规定了数据的位传输顺序(bit ordering),即 MSb First。关于字节序和位序的其他诸多问题,可参考《存储和传输/大小端字节序概念、决定因素、给编程带来的困扰》、《存储和传输/探究普通结构和位域结构体数据在内存中的字节对齐规》、《语言基础/分析和实践 C&C++ 位域结构数据类型》、《网络通信/协议栈内网络字节序与主机字节序的转换实现》等文章,这里不再赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/870544.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

<数据集>安全帽和安全背心识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;22141张 标注数量(xml文件个数)&#xff1a;22141 标注数量(txt文件个数)&#xff1a;22141 标注类别数&#xff1a;3 标注类别名称&#xff1a;[helmet, vest, head] 序号类别名称图片数框数1helmet15937572402v…

程序员如何写PLC程序

PLC是可编程逻辑控制器的简称&#xff0c;常用的编程语言是IEC61131-3&#xff08;梯形图、结构化文本、指令表、功能块、顺序功能图&#xff09;和西门子的SCL。程序员常用的编程语言是JS、Java、Python、C/C、Go等。PLC广泛采用编程工具有codesys、博图等。程序员常用的编程工…

XSS DOM破坏实战案例

目录 案例一 思考 源码分析 查找问题 实现 案例二 查看源码 问题查找 实现 实验环境&#xff1a;DOM clobbering | Web Security Academy (portswigger.net) 案例一 里面是一篇篇的博客&#xff0c;点击进去里面是一些评论 思考 尝试一些常规的xss 没什么效果... 他将…

为什么穷大方

为什么有些人明明很穷&#xff0c;却非常的大方呢&#xff1f; 因为他们认知太低&#xff0c;根本不懂钱的重要性&#xff0c;总是想着及时享乐&#xff0c;所以一年到头也存不了什么钱。等到家人孩子需要用钱的时候&#xff0c;什么也拿不出来&#xff0c;还到处去求人。 而真…

【Qt】常用控件QCheckBox

常用控件QCheckBox QCheckBox表示复选按钮&#xff0c;可以允许选中多个。 QCheckBox继承自QAbstractButton 例子&#xff1a;获取复选按钮的取值 使用Qt Designer先大体进行设计 代码实现&#xff1a; #include "widget.h" #include "ui_widget.h"Widge…

Python爬虫——爬取某网站的视频

爬取视频 本次爬取&#xff0c;还是运用的是requests方法 首先进入此网站中&#xff0c;选取你想要爬取的视频&#xff0c;进入视频播放页面&#xff0c;按F12&#xff0c;将网络中的名称栏向上拉找到第一个并点击&#xff0c;可以在标头中&#xff0c;找到后续我们想要的一些…

不能使用乘除法、for、while、if、else、switch、case求1+2+3+...+n

求123...n_牛客题霸_牛客网 (nowcoder.com) 描述 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 数据范围&#xff1a; 0<n≤2000<n≤200 进阶&#xff1a; 空间复杂度 O(1)O(…

MySQL:查询(万字超详细版)

&#x1f48e;所属专栏&#xff1a; MySQL &#x1f48e;1. 单表查询 &#x1f48e;1.1 全列查询和指定列查询 全列查询&#xff1a; select * from exam; 在实际开发中不要使用 * 来进行查询&#xff0c;因为数据库会很大&#xff0c;影响效率 指定列查询&#xff1a; se…

Redis未授权访问漏洞利用合集

一、基本信息 靶机&#xff1a;IP:192.168.100.40 攻击机&#xff1a;IP:192.168.100.60 二、漏洞 & 过程 Redis 未授权访问漏洞利用无口令远程登录靶机 靶机 cd redis-4.0.8/src./redis-server ../redis.conf 攻击机 ./redis-cli -h 192.168.100.40 Redis 未授权访问…

eNSP 华为ACL配置

华为ACL配置 需求&#xff1a; 公司保证财务部数据安全&#xff0c;禁止研发部门和互联网访问财务服务器&#xff0c;但总裁办不受影响 R1&#xff1a; <Huawei>sys [Huawei]sys Router1 [Router1]undo info-center enable [Router1]int g1/0/0 [Router1-GigabitEth…

openharmony 南向开发基础:ohos自定义子系统,自定义部件,调用hilog部件,hilog日志封装傻瓜式教程

openharmony 南向开发基础:ohos自定义子系统,自定义部件,调用hilog部件,hilog日志封装 自定义单部件 关于开源鸿蒙的南向教程不多,很多都是从官方文档上抄的的例子,官网的例子不是很适合入门,写的很粗糙,不适合傻瓜阅读,毕竟对于刚入行鸿蒙的新手而言,gn语法就是第一劝退魔咒…

【k8s从节点报错】error: You must be logged in to the server (Unauthorized)

k8s主节点可以获取nodes节点信息&#xff0c;但是从节点无法获取&#xff0c;且报错“error: You must be logged in to the server (Unauthorized)” 排查思路&#xff1a; 当时证书过期了&#xff0c;只处理的主节点的证书过期&#xff0c;没有处理从节点的 kubeadm alpha …

解锁 Starknet 的深层洞察:利用 Dune 构建动态数据可视化

原文&#xff1a;https://dev.to/lordghostx/queries-to-insights-visualizing-starknet-data-with-dune-j8p 作者&#xff1a;LordGhostX 编译&#xff1a;TinTinLand Starknet 的链上数据为其区块链生态系统提供了丰富的洞察。它为用户活动、交易模式和网络交互提供了全面…

【系统架构设计】系统规划

【系统架构设计】系统规划 项目的提出和选择可行性研究与效益分析方案的制订和改进新旧系统的分析和比较 项目的提出和选择 Noriaki Kano 提出了顾客质量模型图 假想质量 &#xff1a; 是客户想当然认为产品应该具备的功能或性能&#xff0c;客户并不能正确描述自己想当然要得…

8.MySQL知识巩固-牛客网练习题

目录 SQL228 批量插入数据 描述 SQL202 找出所有员工当前薪水salary情况 描述 示例1 SQL195 查找最晚入职员工的所有信息描述 示例1 SQL196 查找入职员工时间排名倒数第三的员工所有信息描述 SQL201查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t 描述 SQL…

记一次数据库慢查询的处理方法

1.案发现场 今天打开系统&#xff0c;发现有个页面一直报接口超时&#xff0c;然后定位到该接口和对应的查询sql&#xff0c;拿到navicat中去执行发现执行效率确实很慢&#xff0c;sql和执行时间如下&#xff1a;SELECT DISTINCTr.id,r.province,r.city,r.district,r.NAME,r.lo…

【C++指南】深入剖析:C++中的引用

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言&#xff1a; 一、引用的基本概念 1. 定义与特性 2. 语法与声明 二、引用的进阶用法 1. 函…

[HNCTF 2022 WEEK2]getflag-入土为安的二十一天

难点读程序&#xff0c;写exp *(unsigned __int8 *)(i a1) >> 4: 这将字节 i a1 右移 4 位&#xff0c;提取出字节的高 4 位。 *(_BYTE *)(i a1): 这获取原字节的低 4 位&#xff08;即&#xff0c;i a1 位置的字节的低 4 位&#xff09;。 (16 * *(_BYTE *)(i a1))…

怎么在网络攻击中屹立不倒

在当今蓬勃发展的网络游戏产业中&#xff0c;服务器安全无疑是企业生存与发展的基石。面对互联网环境中无处不在的DDoS&#xff08;分布式拒绝服务&#xff09;与CC&#xff08;挑战碰撞&#xff09;攻击威胁&#xff0c;游戏服务器的防御能力与高效处理能力显得尤为重要。相较…

EmguCV学习笔记 VB.Net 2.S 特别示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 教程VB.net版本请访问&#xff1a;EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问&#xff1a;EmguCV学习笔记 C# 目录-CSD…