我刚刚开始使用网络编程,但我无法跟上其中的一些问题。也就是因为隐藏在我身边的引擎盖下面有很多自动魔法物品,我无法理解这一切。在我当前的应用程序中,我接受用户输入:
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)?如果是这样,我怎么访问它?
我看过的很多网站都在谈论标题,而不是。这似乎是非常具体的事情。但我不明白这个虚幻的标题是如何工作的..我想用段号,总段等来定义我自己的标题,但我根本不知道如何去做。我的googleing并没有让我朝着正确的方向发送..!
答案 0 :(得分:4)
UDP不包含标题,段号和总段数。实际上,UDP数据报除了sendto
的缓冲区外什么都不包含。
您可以通过将其添加到邮件中来添加额外信息。而不是简单地将您的消息放入缓冲区,而是创建一个更大的缓冲区,您可以在其中放置您想要的任何“标题”信息,然后将消息放入其中。
从UDP的角度来看,它所看到的只是数据。由接收端的程序来解析这些数据,并认识到某一部分是元数据,而另一部分是常规数据。
您必须定义消息格式,以便接收程序很容易提取缓冲区的“标题”部分。有两种常见的方案:固定标头和可变长度标头。
如果要使用固定标头,则假设每条UDP消息的前X个字节都是元数据。你选择X并且它永远不会改变每条消息。接收者然后知道将X字节读作标题,其余所有作为消息。
如果您要使用可变长度标头,则需要能够告知接收端每个特定消息的标头有多长。一种常见的方案是标头的前4个字节包含一个整数,表示消息的标题部分有多长。然后接收端读取那么多字节并将其解释为标头。然后它读取剩余的数据并将其解释为消息。
最后,源IP和目标IP不是UDP消息的属性,而是套接字的属性。您可以通过检查套接字本身来检索此信息。
答案 1 :(得分:3)
当您使用操作系统的标准接口(socket()
与SOCK_DGRAM
,sendto()
,recvfrom()
等)时,应用程序无法使用UDP标头。它们由操作系统的网络堆栈自动处理。它们会在您发送邮件时自动添加,并在您收到邮件时自动删除。
根据操作系统的不同,有一些方法可以直接在IP路由层上编写和管理UDP头,但这当然不常见,可能需要管理权限。
如果您想为自己的目的定义自己的标题,则必须在邮件正文中执行此操作,即解析并解释您发送和接收的内容sendto()
和recvfrom()
,从而创建什么叫做应用程序协议。网络是一种分层架构,应用程序位于UDP或TCP上,位于IP(通常)位于以太网或Wi-Fi上。每个都有自己的标题,当数据被处理到上面的层时被剥离,你只得到你在应用层发送的内容(也许你可能会错过一些数据包或让它们乱序,因为UDP没有给出那些保证,就像TCP那样。)
答案 2 :(得分:0)
您可以根据打开的套接字接收UDP标头。您可以使用socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
如果为recvfrom
启用此套接字,则会收到包含标头的完整数据包。