如何访问和修改我的 UDP 标头?
我刚刚开始网络编程,但我在跟上一些东西方面遇到了困难。那是因为有很多自动魔法的东西隐藏在我看不见的地方,而我无法理解这一切。在我当前的应用程序中,我像这样接受用户输入:
char buff[1024];
cout << "Enter a message:";
fgets(buff, 1024, stdin);
并且我可以通过基本上执行以下操作轻松地发送该输入:
sendto(m_socket, buff, size, flags, (SOCKADDR*)&addr, sizeof(addr));
其他变量(大小、标志等)显然是在输入和 sendto 调用之间的某个位置进行初始化和配置的。
这一切都工作正常,另一端也可以正常接收数据。服务器执行此操作
recvfrom(m_socket, (char*)data, max, flags, (SOCKADDR*)&fromAddr, &fromLength)
,然后我可以将“数据”打印到控制台中,这就是我的消息。
那么我的 UDP 数据包标头到底在哪里?我必须指定它吗?当我传入一些数据时,标准 UDP 数据包的“数据”部分是否填充了我指定的数据,并且标头自动为我填充(源 IP、目标 IP)?如果是这样,我该如何访问它?
我浏览过的很多网站都讨论了标题和其他内容。这似乎是一个非常具体的事情。但我不明白这个虚幻的标头是如何工作的。我想用段号、总段等来定义我自己的标头,但我根本不知道如何去做。我的谷歌搜索也没有引导我走向正确的方向..!
I am just starting out with network programming and I am having trouble keeping up with some of the stuff. Namely because there is a lot of auto-magic stuff going on under the hood that is hidden away from me, and I cant get my head around it all. In my current app, I take user input like so:
char buff[1024];
cout << "Enter a message:";
fgets(buff, 1024, stdin);
And i can easily send that off by essentially doing this:
sendto(m_socket, buff, size, flags, (SOCKADDR*)&addr, sizeof(addr));
The other variables (size,flags,etc) are obviously initialized and configured somewhere between the input and sendto call.
This all works fine, and the other end receives the data fine. the server does
recvfrom(m_socket, (char*)data, max, flags, (SOCKADDR*)&fromAddr, &fromLength)
and I can then just print out 'data' into the console, and it'd be my message.
So where exactly is my UDP packets header? Did i have to specify it? when i pass in some data, is the 'data' part of a standard UDP packet filled with the data i specify, and the header automatically populated for me (source IP, destination IP)? If so how do i even access it?
A lot of websites I have looked at talk about headers and what not. It seems to be this very specific thing. But I dont understand how this illusive header works.. I'd like to define my own header with things like segment number, total segments, etc. but i dont know how to go about this at all. My googleing isnt sending me in the right direction either..!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您使用操作系统的标准接口(
socket()
和SOCK_DGRAM
、sendto()
时,UDP 标头对应用程序不可用、recvfrom()
等)。它们由操作系统的网络堆栈自动处理。它们会在您发送消息时自动添加,并在您接收时自动删除。根据操作系统的不同,您可以通过某些方法直接在 IP 路由层上编写和管理 UDP 标头,但这肯定不常见,并且可能需要管理权限。
如果您想根据自己的目的定义自己的标头,则必须在消息正文中执行此操作,即解析和解释您发送和接收的内容
sendto()
和recvfrom()
,从而创建了所谓的应用程序协议。网络是一种分层架构,其中应用程序位于 UDP 或 TCP 上,IP 位于(通常)位于以太网或 Wi-Fi 上。每个数据包都有自己的标头,当数据处理到上一层时,这些标头会被剥离,并且您只能收到在应用程序层上发送的内容(也许您可能会丢失一些数据包或使它们乱序,因为 UDP 不提供你可以保证这些保证,就像 TCP 所做的那样)。The UDP headers are not available to the application when you use the standard interfaces from the operating system (
socket()
withSOCK_DGRAM
,sendto()
,recvfrom()
and such). They are automatically handled by the operating system's network stack. They are automatically added when you send the message and automatically stripped when you receive.Depending on the operating system, there are some means you can write and manage the UDP headers directly over the IP routing layer, but that is certainly unusual, and would probably require administrative privileges.
If you want to define your own headers for your own purposes, you must do so inside the body of the message, i.e. parse and interpret what you send and receive
sendto()
andrecvfrom()
, thus creating what is called an application protocol. Networking is a layered architecture, where applications sits upon UDP or TCP, that sits upon IP that (usually) sits upon Ethernet or Wi-Fi. Each one has its own headers that is stripped when the data is handled to the above layer, and you only gets what you send on the application layer (maybe you can miss some packets or get them out of order, because UDP doesn't give you those guarantees, as TCP does).UDP 不包含报头、段号和总段等内容。事实上,UDP 数据报除了您
发送到
的缓冲区之外什么都不包含。您可以通过将其包含在消息中来添加额外信息。不要简单地将消息放入缓冲区,而是创建一个更大的缓冲区,在其中放入您想要的任何“标头”信息,然后再放入消息。
从UDP的角度来看,它看到的只是数据。由接收端的程序解析这些数据并认识到其中的一部分是元数据,另一部分是常规数据。
您必须定义消息格式,以便接收程序可以轻松提取缓冲区的“标头”部分。有两种常见的方案:固定标头和可变长度标头。
如果您要使用固定标头,则假设每个 UDP 消息的前 X 字节是元数据。你选择 X,它在每条消息中都不会改变。然后,接收者知道将 X 字节读取为标头,并将其余字节读取为消息。
如果您要使用可变长度标头,则需要能够告诉接收端每条特定消息的标头有多长。常见的方案是标头的前 4 个字节包含一个整数,表示消息的标头部分有多长。然后接收端读取那么多字节并将其解释为标头。然后它读取其余数据并将其解释为消息。
最后,源 IP 和目标 IP 不是 UDP 消息的属性,而是套接字的属性。您可以通过检查套接字本身来检索此信息。
UDP does not contain such things as headers, segment numbers and total segments. In fact, a UDP datagram contains nothing except the buffer that you
sendto
.You can add extra information by including them with your message. Instead of simply putting your message in your buffer, make a larger buffer into which you put whatever "header" information you would like and then put your message afterwards.
From UDP's perspective, all it sees is data. It is up to the program on the receiving end to parse this data and realize that a certain part it is metadata and the other part of it is regular data.
You will have to define your message format such that it is easy for the receiving program to extract the "header" portion of the buffer. There are two common schemes: fixed headers and variable length headers.
If you are going for a fixed header, you assume that the first X bytes of every UDP message are metadata. You pick the X and it never changes per message. The recipient then knows to read X bytes as the header and all the rest as a message.
If you are going for a variable length header, you need to be able to tell the receiving end how long the header is for each particular message. A common scheme is that the first 4 bytes of the header contain an integer which says how long the header part of the message is. Then the receiving end reads that many bytes and interprets that as the header. Then it reads the rest of the data and interprets that as the message.
Lastly, the source IP and the destination IP are not properties of your UDP messages but rather properties of your socket. You can retrieve this information by inspecting the socket itself.
您可以根据您打开的套接字接收 UDP 标头。您可以使用
socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))接收完整的数据包;
如果此套接字启用了
recvfrom
,那么您将收到包括标头的完整数据包。You can receive the UDP headers based the sockets you open up. You can receive the complete packet using
socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
If this socket is enabled for
recvfrom
then you receive the complete packet including your headers.