网络数据大端序和小端序

实际应用场景

1. 网络协议解析

swift 复制代码
// 假设接收到的消息格式:
// [4字节nonce长度][nonce数据][实际载荷数据]
let message: Data = ... // 接收到的完整消息

// 读取nonce长度
let nonceLength = message[..<4].withUnsafeBytes {
    Int($0.loadUnaligned(as: Int32.self).byteSwapped)
}

// 提取nonce数据
let nonceRange = 4..<(4 + nonceLength)
let nonceData = message[nonceRange]

// 剩余的是实际载荷
let payloadRange = (4 + nonceLength)..
let payloadData = message[payloadRange]

字节序的重要性

为什么需要 .byteSwapped

swift 复制代码
// 假设网络传输的数据是大端序:0x00 0x00 0x01 0x00 (表示256)
let networkData = Data([0x00, 0x00, 0x01, 0x00])

// 不加 byteSwapped(错误):
let wrongLength = networkData.withUnsafeBytes { 
    Int($0.loadUnaligned(as: Int32.self)) // 得到 65536 ❌
}

// 加 byteSwapped(正确):
let correctLength = networkData.withUnsafeBytes { 
    Int($0.loadUnaligned(as: Int32.self).byteSwapped) // 得到 256 ✅
}

安全考虑

loadUnaligned vs load

swift 复制代码
// 使用 loadUnaligned 更安全,因为:
message[..<4].withUnsafeBytes {
    // 这4个字节可能没有按照Int32的内存对齐要求
    Int($0.loadUnaligned(as: Int32.self).byteSwapped) // ✅ 安全
}

// 如果用 load,在某些架构上可能崩溃
message[..<4].withUnsafeBytes {
    Int($0.load(as: Int32.self).byteSwapped) // ❌ 可能崩溃
}

完整的工作流程

swift 复制代码
func parseEncryptedMessage(_ message: Data) -> (nonce: Data, payload: Data)? {
    guard message.count >= 4 else { return nil }
    
    // 1. 读取nonce长度
    let nonceLength = message[..<4].withUnsafeBytes {
        Int($0.loadUnaligned(as: Int32.self).byteSwapped)
    }
    
    // 2. 验证数据完整性
    let expectedTotalLength = 4 + nonceLength
    guard message.count >= expectedTotalLength else {
        print("消息不完整: 期望 \(expectedTotalLength) 字节,实际 \(message.count) 字节")
        return nil
    }
    
    // 3. 提取各部分数据
    let nonce = message[4..<(4 + nonceLength)]
    let payload = message[(4 + nonceLength)...]
    
    return (Data(nonce), Data(payload))
}

这段代码典型用于安全通信协议 中,用于解析包含随机数(nonce)的加密消息格式,确保每次加密使用的随机数都是唯一的,防止重放攻击。 不,字节序转换后数据的数值会改变! 这是很多人容易混淆的地方。

让我用具体例子来说明:

数值变化的例子

swift 复制代码
let original: Int32 = 0x12345678  // 十进制: 305419896

print(String(format: "原始值: 0x%08x = %d", original, original))
// 输出: 原始值: 0x12345678 = 305419896

let swapped = original.byteSwapped

print(String(format: "交换后: 0x%08x = %d", swapped, swapped))
// 输出: 交换后: 0x78563412 = 2018915346

可以看到数值从 305419896 变成了 2018915346!

为什么数值会变化?

因为字节序改变的是字节的排列顺序,而不是数据本身:

内存布局对比

ini 复制代码
原始值 0x12345678:
大端序: 12 34 56 78
小端序: 78 56 34 12

byteSwapped 后:
大端序: 78 56 34 12 = 0x78563412
小端序: 12 34 56 78 = 0x12345678

正确的使用场景

byteSwapped 的目的是纠正字节序不匹配,而不是保持数值不变:

场景1:网络数据解析(正确用法)

swift 复制代码
// 网络发送的数据(大端序):0x00 0x00 0x01 0x00 表示 256
let networkData = Data([0x00, 0x00, 0x01, 0x00])

// 在小端序系统上解析:
let rawValue = networkData.withUnsafeBytes { 
    $0.loadUnaligned(as: Int32.self) 
}
print(rawValue) // 65536 ❌ 错误!

let correctedValue = networkData.withUnsafeBytes { 
    $0.loadUnaligned(as: Int32.self).byteSwapped 
}
print(correctedValue) // 256 ✅ 正确!

场景2:错误的转换

swift 复制代码
// 本地创建的数据(小端序)
let localValue: Int32 = 256  // 内存中: 00 01 00 00

// 错误地使用 byteSwapped
let wrongValue = localValue.byteSwapped
print(wrongValue) // 65536 ❌ 本地数据不需要交换!

// 正确的做法:只有跨平台数据才需要交换

什么时候数值会"看起来"一样?

只有在对称的字节模式时,交换前后数值可能相同:

swift 复制代码
let symmetric1: Int16 = 0x1234
let swapped1 = symmetric1.byteSwapped  // 0x3412 = 13330 ❌ 不同

let symmetric2: Int16 = 0x1212  
let swapped2 = symmetric2.byteSwapped  // 0x1212 = 4626 ✅ 相同(巧合)

let symmetric3: Int32 = 0x12344321
let swapped3 = symmetric3.byteSwapped  // 0x21433412 = 558161938 ❌ 不同

总结

关键理解:

  • byteSwapped 改变字节顺序,因此数值一定会变化
  • 它的用途是纠正因平台字节序差异导致的错误解析
  • 只有在"错误字节序"的数据上使用 byteSwapped 才能得到"正确数值"
  • 在"正确字节序"的数据上使用 byteSwapped 反而会得到错误数值

所以在你之前的代码中:

swift 复制代码
let nonceLength = message[..<4].withUnsafeBytes {
    Int($0.loadUnaligned(as: Int32.self).byteSwapped)  // 这里假设数据是大端序
}

这个操作是基于一个前提:接收到的网络数据使用大端序,而当前系统使用小端序

相关推荐
mit6.82413 小时前
固定中间
算法
老马啸西风14 小时前
成熟企业级技术平台 MVE-010-跳板机 / 堡垒机(Jump Server / Bastion Host)
人工智能·深度学习·算法·职场和发展
立志成为大牛的小牛14 小时前
数据结构——五十九、冒泡排序(王道408)
数据结构·学习·程序人生·考研·算法
s090713614 小时前
下视多波束声呐进行测绘作业注意事项
算法·海洋测绘·下视多波束
papership14 小时前
【入门级-数据结构-3、特殊树:完全二叉树的定义与基本性质】
数据结构·算法
中國龍在廣州14 小时前
AI顶会ICML允许AI参与审稿
人工智能·深度学习·算法·机器学习·chatgpt
立志成为大牛的小牛14 小时前
数据结构——六十、快速排序(王道408)
数据结构·程序人生·考研·算法·排序算法
Dev7z14 小时前
基于MATLAB的GA–PSO混合算法无线传感器网络节点部署优化研究
网络·算法·matlab
koo36414 小时前
12.14周报
人工智能·算法