【问题标题】:Sending UDP packets in the correct Endianness以正确的字节顺序发送 UDP 数据包
【发布时间】:2016-06-16 21:55:13
【问题描述】:

我无法理解网络字节顺序以及通过 UDP 发送和接收数据的顺序。我正在使用 C#。

我有一个结构持有:

message.start_id         = 0x7777CCCC;
message.message _id      = 0xBBB67000;
     more data

消息定义有[StructLayout(LayoutKind.Sequential)]。我首先使用以下方法将结构转换为字节数组:

public byte[] StructureToByteArray(object obj)
{ 
    int len = Marshal.SizeOf(obj);
    byte[] arr = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(obj, ptr, true);
    Marshal.Copy(ptr, arr, 0, len);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

然后我检查字节顺序:

if (BitConverter.IsLittleEndian)
{
    Array.Reverse(packet);
}

那我就发了

socket.SendTo(packet, endPoint);

当我发送这个时,接收端接收到的消息应用了正确的字节顺序,但是字节顺序相反,所以在wireshark中我得到:

剩下的.....BBB67000 7777CCCC

当我期待时:7777CCCC BBB67000 ...........其余的。

我的期望是正确的还是正常的,结构中的第一个字节是最后一个到达的?

【问题讨论】:

  • 字节序不应该应用于整个数据包 - 它应该应用于各个部分......我认为它是每 32 位,但我不是 100% 的。跨度>
  • 和迈克尔·布雷说的差不多。字节序应用于各个部分(对于start_idmessage_id 分别应用),并且它是在字节级别的(所以在一个 4 字节的 int 中,第一个与第四个字节交换,第二个与第三)

标签: c# arrays udp endianness


【解决方案1】:

我无法理解网络字节顺序以及通过 UDP 发送和接收数据的顺序

通过 UDP 发送和接收的数据与提供给套接字的字节顺序完全相同。您只发送或接收字节数组,而 UDP 根本不会重新排序数据报中的字节。

那么问题来了,如何处理字节序?

嗯,在很多情况下,答案是“没有”。一方面,您今天遇到的大多数计算机都运行 x86 架构并且始终使用 little-endian。在许多情况下,无论如何您都可以控制两端,因此始终可以坚持使用其中一个。如果您的 API 有办法在字节流之间进行转换,您可以直接使用 UDP 套接字发送和接收这些字节。

但是,是的,有时您需要能够以不同于运行程序的架构本机支持的字节序传输数据。

在您的特定示例中,您似乎选择使用大端序作为协议的字节顺序(我从一小段代码中推断出这一点……如果没有a good Minimal, Complete, and Verifiable example,真的不可能确定)。这很好;原始 BSD 套接字 API 包含“网络字节顺序”的概念,即大端。套接字库包括要转换的函数,例如从“主机顺序”到“网络顺序”并返回的 16 位整数。

但重要的是要了解字节序会在数据中每个单独的基元级别影响您的数据。您不能一次全部反转整个字节数组,因为如果您这样做,不仅会改变每个单独基元的字节顺序,还会改变基元本身的顺序。果然,您在 Wireshark 跟踪中看到了这一点:数据结构中的两个字段的顺序已交换。

要正确处理字节顺序,您必须遍历数据结构的每个字段并单独交换字节。您将不理会字节,short 值(16 位)将交换它们的字节对,int 值(32 位)将它们的四字节序列颠倒,long 值(64 位) ) 将有 8 个字节反转,依此类推。

为了让事情变得更复杂,一些数据结构根本不受字节序的影响(例如 UTF8 编码的文本),而另一些则具有更复杂的规则(例如 Windows GUID/UUID,它是一个 128 位值实际上被定义为一个复杂的数据结构,具有多个不同大小的字段)。

要记住的重要一点是,字节序始终应用于每个单独的原始数据值的级别,同时考虑到原始数据值使用的实际字节数。

【讨论】:

  • 嗨彼得,非常感谢您的回复。我查看了 MS 提供的各种功能(htonl 等),但找不到任何用于 uint、doubles 等的东西。我在需要发送的结构中混合了所有内容。由于所有值都是 32 位,因此我通过一次遍历 1 个字节的结构手动交换字节结构中的字节,复制到一个新字节,执行一个数组。反向并将其复制回相同大小的新字节结构.我已经在电线上对其进行了测试,它似乎可以工作:\。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 2013-09-15
  • 1970-01-01
  • 2017-06-26
相关资源
最近更新 更多