UDP如何工作?
IETF(Internet工程任务组)是一个由工程师和计算机科学家组成的社区,他们致力于引入不同的新Internet技术,标准和规范。
RFC是IETF发布的文档。
它通常是为同行评审而正式编写的。
通常,它讨论不同的协议方法及其完整的细节和功能。
它主要用作工程师执行,提供反馈,提交与协议相关的新信息及其概念的标准文档(还包括一些建议,因此称为“征求意见”)。
为什么在这里讨论IETF和RFC?
这是因为名为RFC 768的RFC可能是最短的(只有几段没有协议的详细信息)。
RFC通常非常详细,有数百页。
但是,这确实是非常简短和紧凑的。
这是因为它处理的协议称为UDP(用户数据报协议),它具有较低的复杂度并且非常简单(与之相对的TCP由于复杂的可靠性机制而有点复杂)。
TCP/IP参考模型包含5个不同的层。
这些层执行不同的工作,以实现正确的网络通信。
顶层是应用程序层。
该层为软件/应用程序提供了一种使用支持的协议(如HTTP,FTP,SMTP)通过网络进行通信的方法。
然后是传输层,TCP和UDP(我们的讨论主题)就在这里。
TCP提供可靠的通信,而UDP不提供任何保证的传递机制。
UDP也不提供任何形式的传递机制。
然后是IP层,它提供了将内容传递到目标IP地址的方法。
然后到最后的是数据链路层,其中在顶部添加了物理地址(MAC),以通过物理层将消息转发到网关。
层 | 功能 |
---|---|
应用层 | 此处是应用层协议,如http,ftp,smtp sits。应用程序使用支持的协议启动通信 |
传输层 | 增加了很多功能,以便正确交付消息。基本上它与TCP的可靠性(在某些情况下,使用UDP也可以使用不可靠 - 不可靠的选项)。 |
网络层 | 这是IP地址进入图片的地方。该层不提供任何类型的可靠性。 |
数据链接层 | 添加MAC地址源和目的地(网关)的详细信息 |
物理层 | 这是网络硬件进入图片的地方。 |
无论使用TCP还是UDP,IP都是使它们在网络上工作的协议(这是因为TCP和UDP位于传输层,而IP位于网络层)。
如果我们看到上表,则通信从应用程序层开始,然后向下经过不同的层。
每层将继续在其上一层提交的数据之上添加自己的字段和标头。
在源头,各层添加自己的信息,而在目的地,各层在将信息提交给上层之前将其剥离。
因此,基本上,我们可以根据需要选择TCP或者UDP,但是IP将用于使网络通信成为可能。
我们不会在本文中讨论TCP。
这是因为它有点复杂,并且需要自己的文章。
UDP是两者中使用最少的。
这是因为我们每天使用的大多数应用程序都需要可靠性。
UDP基本上是一种面向消息的协议。
在某种程度上,UDP和IP非常相似。
因为IP还不提供任何形式的交付保证或者可靠性机制。
让我们将tcpdump带入图中,看看建立UDP连接时会发生什么。
Tcpdump是捕获进入和离开系统的网络数据包的工具。
它几乎可以在所有Linux发行版上使用。
Tcpdump我们查看网络流量的详细信息和内容。
为了理解这一点,我们需要首先模拟到某个地方的UDP请求,同时让我们捕获网络数据包。
让我们向远程服务器(在一个终端上)发出DNS请求,然后在另一个终端上捕获数据包并查看详细信息。
相关:域名系统(DNS)如何工作?
在第一终端上(执行以下命令):
ubuntu@testing:~$sudo tcpdump -n -vvv host 8.8.8.8 and port 53
在第二终端上(执行以下命令):
ubuntu@testing:~$dig @8.8.8.8 www.google.com
在第二个终端上执行上述命令后,我们应该在第一个终端中看到消息流。
该消息将如下所示。
18:40:39.758842 IP (tos 0x0, ttl 64, id 4636, offset 0, flags [none], proto UDP (17), length 56) 192.168.40.27.55625 > 8.8.8.8.53: [udp sum ok] 63851+ A? google.com. (28) 18:40:39.812844 IP (tos 0x0, ttl 59, id 53901, offset 0, flags [none], proto UDP (17), length 104) 8.8.8.8.53 > 192.168.40.27.55625: [udp sum ok] 63851 q: A? google.com. 3/0/0 google.com. [32s] A 172.217.26.174, google.com. [32s] A 172.217.26.174, google.com. [32s] A 172.217.26.174 (76)
第一行指示IP数据包的内容。
它没有与UDP协议有关的任何内容。
字符串“ proto UDP(17)”表示一个8位字段,用于标识下一个协议级别。
不同的协议有不同的十进制表示法。
如果它是TCP而不是UDP,那么我们现在在输出中看到的将是6而不是17.
如果IP头中没有该字段(协议字段),则接收端将不知道IP数据包所携带的协议的类型。
甚至可能是ICMP,GRE等。
在我们的例子中,它的UDP是数字17.
因此最重要的是,它不包含与UDP相关的任何内容,而只是告诉该IP数据包的内容具有UDP数据。
记住UDP及其详细信息与应用程序数据一起封装在IP数据包中的事实(正如我们前面所讨论的,目标位置将剥离与每一层关联的每一位数据,并将其提交给向上移动到应用程序层的下一层) 。
“ id 4636”是IP标识字段的一部分。
当发生碎片时,这实际上很有用。
当IP数据包很大,并且中间网络设备不支持发送它时,则需要对IP数据包进行分段。
然后将不同的片段发送到目的地。
在目的地,应该进行某种识别以重新组装接收到的片段。
所有分段的数据包将具有相同的标识字段号。
因此,接收器会将它们全部视为同一数据包的一部分。
如果没有碎片发生(例如在我们的案例中),则大多数IP标头将具有唯一的标识号。
“ tos 0x0”指示服务类型。
TOS(服务类型)指示应如何处理数据包。
基本上,某些数据包可能需要特别注意(例如语音电话调用)。
“ ttl 64”表示生存时间。
在到达最终目的地之前,此IP数据包可以通过的最大网络设备数。
如果源和目标之间有68个设备,我们的IP数据包将被丢弃在第64个设备上(因为我们的ttl是64),并且不会到达目标。
不同系统之间的默认值是不同的。
建议:TTL(生存时间)在Traceroute中扮演什么角色
“偏移0”也与IP分组的分段有关。
默认情况下,它始终设置为0。
如果存在某种分段,则分段的数据包都将具有相同的id字段(如前所述),并且还将具有offset字段,该字段指示数据在重新分配时应放入的位置组装。
让我们考虑一个碎片化的例子。
假设分片系列中的第一个数据包具有“标识字段:100和偏移值:0”,而分片系列中的第二个数据包具有“标识字段:100和偏移值:170”。
这意味着第二个IP分片数据将适合在重新组装过程中紧接在第一个数据包数据之后(170 x 8 = 1360字节)。
现在让我们进入我们的主要主题。
UDP。
那是显示的tcpdump输出中的第二行(192.168.40.27.55625> 8.8.8.8.53:[udp sum ok] 63851+ A?google.com。(28))
该行中有5个主要组件要讨论。
UDP
我们看到的IP地址实际上实际上也是IP数据包的一部分。
IP地址不是UDP的一部分。
IP地址存在于IP层(我们在第一行中讨论的层。
源IP地址192.168.40.27,这是我的笔记本电脑的IP地址。
8.8.8.8是google的公共DNS地址,我们最初向其发送DNS请求)使用第二个终端)。
UDP的标头字段是无效的
- 源端口:这是发送UDP请求时选择的随机端口号(在我们的示例中为55625,从第二行可以明显看出)。
- 目标端口:这是我们向其发送请求的应用程序的目标端口号。 DNS使用默认端口号53,与我们的示例相同。
- 长度:从请求的应用程序发送的实际用户数据总量。在我们的例子中,由dig工具发送的DNS请求)以字节+ UDP标头长度表示。第二行的最后一个字段是数字(28)。即28个字节的用户数据。 UDP数据包有8个字节的标头字段数据。这意味着我们的UDP数据包的长度为28 + 8 = 36
- 校验和:UDP校验和的计算有点复杂。我将写一篇专门的文章,介绍如何计算UDP和TCP校验和(对于TCP和UDP,校验和的计算方法相同)。尽管上面的tcpdump输出中未显示校验和值,但它看起来像0xaab0或者0x8921或者类似的值。
相关:如何计算UDP和TCP校验和?
- 有效负载:这是客户端应用程序发送的实际请求。在本例中,其实际的有效负载是由dig(63851+ A?google.com。生成的dns请求。A代表google.com的A记录请求。63851+是DNS事务ID。它可以帮助dns客户端识别响应。)。
关于UDP校验和要记住的一件事是它是可选的。
UDP校验和在协议级别没有强制执行。
校验和可以帮助识别数据在传输过程中是否发生了更改,或者是否被篡改,更改等。
它在UDP中提供了一种“错误检测”机制。
UDP为什么有一个用于错误检测的校验和字段?
这是个好问题。
和一个有效的问题。
因为UDP承诺其重量轻且没有任何类型的可靠性或者校正机制。
如果UDP连接少且不可靠,为什么它会有一个校验和字段?
UDP不在乎丢弃的数据包和乱序发送的数据包。
但是UDP关心的一件事是接收到的数据包的完整性(尽管是可选的,但提供了完整性验证的规定)。
但是,如果无法纠正完整性问题,使用具有校验和的完整性验证机制又有什么用呢?
同意不能解决完整性问题。
但是它可以丢弃校验和无效的数据报!基本上,接收端不会接受具有错误校验和的数据包。
没有机制可以将此信息通知发件人,但是它将以静默方式将其丢弃。
如果UDP的连接较少,如何识别响应?
8.8.8.8.53> 192.168.40.27.55625:[udp sum ok] 63851 q:A? google.com。 3/0/0 google.com。 [32s] A 172.217.26.174,google.com。 [32s] A 172.217.26.174,google.com。 [32s] A 172.217.26.174(76))
上面显示的是对我们的dns请求的UDP响应(tcpdump输出中的最后一行)。
这里的源IP和源ort是8.8.8.8和53.
目标IP和目标端口是192.168.40.27和55625.
响应中的目标端口与初始请求中的源端口相同(tcpdump输出中的第二行)。
这意味着,响应直接指向发送初始请求的源端口。
这样,客户端程序可以识别正确的响应。
理想情况下,客户端程序等待响应,同时保持源端口打开。
仅当收到响应时,源端口(我必须说是套接字)才关闭。
与UDP相比TCP最佳的用例
想象一下,我们想向数百万用户广播直播视频流(可能是板球比赛)。
TCP涉及大量服务此类请求的开销。
就实时流而言,如果TCP请求过多,则操作系统必须等待所有未确认的数据。
这意味着,如果有数百万个请求,则操作系统会将所有这些未确认的数据保留在缓冲区中。
因此,在这种情况下,TCP是个坏主意。
如果我们需要快速简单的响应,那么UDP是最好的。
例如DNS,NTP等。
想想像游戏这样的场景。
其中游戏的新状态正在不断取代旧状态。
这意味着就客户端而言,旧状态毫无用处(因此,不必再通过面向连接的TCP发送丢失的数据包了)。
UDP是一个不错的选择。