Linux网络 | 学习传输层网络协议之UDP(短篇)
前言:本节内容正式迈入传输层网络协议的知识殿堂, 之前的文章, 我们都是在应用层进行翻来覆去。比如http就是应用层协议, 只不过使用了tcp的系统调用。从本节开始, 友友们将会学习传输层两大协议: UDP和TCP。其中UDP不算特别重要, 但是也要了解。UDP的知识点也比较少, 本节就是讲解UDP。这里博主先说一下讲解思路,这个讲解思路适用于以后学习任何一种协议:首先,先回答报头和有效载荷如何分
前言: 本节内容正式迈入传输层网络协议的知识殿堂, 之前的文章, 我们都是在应用层进行翻来覆去。 比如http就是应用层协议, 只不过使用了tcp的系统调用。 从本节开始, 友友们将会学习传输层两大协议: UDP和TCP。 其中UDP不算特别重要, 但是也要了解。 UDP的知识点也比较少, 本节就是讲解UDP。
这里博主先说一下讲解思路,这个讲解思路适用于以后学习任何一种协议:
- 首先,先回答报头和有效载荷如何分离,有效载荷应该交付给那一个上层协议(对应的协议字段, 协议方案)。
- 第二,就是认识报头。
- 第三,就是学习该协议周边的问题。
ps:本节内容UDP内容比较简单, 友友们放心观看哦!
目录
UDP报头分离
UDP的报文是UDP自动为我们形成的, 就比如我们发送了一个“你好”, 那么UDP就会以“你好”作为数据, 然后添加上报头也就是报文中的八字节报头。
对于UDP来说, 报头的大小是固定的, 就是8字节, 所以将UDP的报头和报文分开非常简单, 就是将报文的前八个字节和后面的字节分开。
UDP报头解析
源端口和目的端口
我们还是使用“你好”这个例子。 在发送一句话中, ”你好“作为数据, 然后操作系统就给我们添加了报头, 其中前四个字节就是UDP的源端口和UDP的目的端口。源端口就是发送方的端口号, 目的端口就是目标主机的端口号。
这两个端口号如何得到的, 客户端是怎么知道目的端口号的和源端口号的呢?
首先, 客户端的端口号我们说过, 客户端的端口号是一个随机的端口号, 是在启动客户端的时候, 操作系统默认从主机中选取得一个空余的端口号。 然后, 目的端口号是服务端得端口号, 而服务端的端口号是固定的, 是内置在客户端内部的。 我们客户端connect的时候, 就是连接的这个内置的端口号。
服务端是怎么知道目的端口号和源端口号的呢?
我们之前写http协议或者tcp协议的时候, 是不是服务端都有一个accept系统调用, 然后输出型参数里面有一个port参数, 这个port参数,其实就是目的端口号。 服务端也一定知道自己的端口号, 这个端口号就是源端口号。
UDP长度和UDP检验和
我们虽然能够利用udp报头的定长特点, 将报头和有效载荷进行分离。 但是我们如何知道我们的数据是一个完整的报文呢? 这个时候就用到了udp的长度。 udp长度,指的是整个报文的长度(udp长度就是指整个报文的长度, 不是有效载荷的长度)。 有了整个报文的长度, 有效载荷的长度直接使用报文长度减去八就行了。另外, 如果想要检验是不是一个完整的报文, 只需要将udp长度和整个报文的长度(sizeof计算) 进行比较, 看看是否一样即可。
udp检验和就是检查udp内容在传输过程中有没有出现偏差。
面向数据报
应用层交给udp多长的报文,udp原样发送, 既不会拆分,也不会合并。
如果发送端调用一次sendto, 发送100字节, 那么接收端也必须调用对应的一次recvfrom, 接收100字节;而不能循环十次调用recvfrom, 每次接受10字节。
UDP缓冲区
UDP没有真正意义上的缓冲区,调用sendto会直接交给内核, 由内核将数据传给网络协议层然后直接进行发送。
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃。
UDP的socket既能读也能写, 这个概念叫做全双工。
UDP报头
UDP报头怎么理解, 我们知道, Linux是用C语言写的, 协议本质上就是一种约定, 有着各种约定, 所以协议我们就可以把它看作一种自定义类型, 只不过不是结构体,而是位段:
struct udp_header
{
uint32_t src_port:16;
uint32_t dst_port:16;
uint32_t length:16;
uint32_t check_code:16;
};
就是上面的这种自定义类型 , 既然是类型,那么就可以定义变量, 那么以后我们定义udp报头, 其实就是创建一个这个类型的变量。
——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!
更多推荐
所有评论(0)