如何访问和修改我的 UDP 标头?

Pro*_*gga 4 c++ udp header packet

我刚刚开始网络编程,但我在跟上一些东西方面遇到了困难。那是因为有很多自动魔法的东西隐藏在我看不见的地方,而我无法理解这一切。在我当前的应用程序中,我像这样接受用户输入:

char buff[1024];
cout << "Enter a message:";
fgets(buff, 1024, stdin);
Run Code Online (Sandbox Code Playgroud)

我可以通过基本上这样做来轻松地发送它:

sendto(m_socket, buff, size, flags, (SOCKADDR*)&addr, sizeof(addr));
Run Code Online (Sandbox Code Playgroud)

其他变量(大小、标志等)显然是在输入和 sendto 调用之间的某个位置进行初始化和配置的。

这一切都工作正常,另一端也可以正常接收数据。服务器做

recvfrom(m_socket, (char*)data, max, flags, (SOCKADDR*)&fromAddr, &fromLength) 
Run Code Online (Sandbox Code Playgroud)

然后我可以将“数据”打印到控制台中,这就是我的消息。

那么我的 UDP 数据包标头到底在哪里?我必须指定它吗?当我传入一些数据时,标准 UDP 数据包的“数据”部分是否填充了我指定的数据,并且标头自动为我填充(源 IP、目标 IP)?如果是这样,我该如何访问它?

我看过的很多网站都讨论了标题和其他内容。这似乎是一个非常具体的事情。但我不明白这个虚幻的标头是如何工作的。我想用段号、总段等来定义我自己的标头,但我根本不知道如何去做。我的谷歌搜索也没有引导我走向正确的方向..!

lve*_*lla 7

当您使用操作系统的标准接口(socket()使用SOCK_DGRAM、等)时sendto(),应用程序无法使用 UDP 标头。recvfrom()它们由操作系统的网络堆栈自动处理。它们会在您发送消息时自动添加,并在您接收时自动删除。

根据操作系统的不同,您可以通过某些方法直接在 IP 路由层上编写和管理 UDP 标头,但这肯定不常见,并且可能需要管理权限。

如果您想为自己的目的定义自己的标头,则必须在消息正文中执行此操作,即解析和解释您发送和接收的内容sendto()recvfrom()从而创建所谓的应用程序协议。网络是一种分层架构,其中应用程序位于 UDP 或 TCP 上,IP 位于(通常)位于以太网或 Wi-Fi 上。每个数据包都有自己的标头,当数据处理到上一层时,这些标头会被剥离,并且您只能收到在应用程序层上发送的内容(也许您可能会丢失一些数据包或使它们乱序,因为 UDP 不提供你可以保证这些保证,就像 TCP 所做的那样)。


Sri*_*ala 6

UDP 不包含报头、段号和总段等内容。事实上,UDP 数据报除了您所使用的缓冲区之外什么也不包含sendto

您可以通过将其包含在消息中来添加额外信息。不要简单地将消息放入缓冲区,而是创建一个更大的缓冲区,在其中放入您想要的任何“标头”信息,然后再放入消息。

从UDP的角度来看,它看到的只是数据。由接收端的程序解析这些数据并认识到其中的一部分是元数据,另一部分是常规数据。

您必须定义消息格式,以便接收程序可以轻松提取缓冲区的“标头”部分。有两种常见的方案:固定标头和可变长度标头。

如果您要使用固定标头,则假设每个 UDP 消息的前 X 字节是元数据。你选择 X,它在每条消息中都不会改变。然后,接收者知道将 X 字节读取为标头,并将其余字节读取为消息。

如果您要使用可变长度标头,则需要能够告诉接收端每条特定消息的标头有多长。常见的方案是标头的前 4 个字节包含一个整数,表示消息的标头部分有多长。然后接收端读取那么多字节并将其解释为标头。然后它读取其余数据并将其解释为消息。

最后,源 IP 和目标 IP 不是 UDP 消息的属性,而是套接字的属性。您可以通过检查套接字本身来检索此信息。

  • UDP 确实有标头,但被网络堆栈隐藏了。Prodigga 显示的这张图片是正确的。IP地址属于较低层的报头。它不是套接字的属性,因为套接字可用于多种协议,其中许多协议没有 IP 地址。 (3认同)