【网络编程】传输层协议——UDP协议

一、传输层的意义

数据从应用层下来并不是直接发送给网络,而是从网络协议栈自顶向下传输,经过传输层、网络层,数据链路层,最后通过硬件发送到网络。
前两章讲了应用层的两个协议:HTTPHTTPS,应用层的主要目的是为了保证数据的安全,而传输层的目的则是为了保证数据能够可靠地传送到目标地址

二、端口号

2.1 五元组标识一个通信

端口号是用来标识一个主机上进行网络通信的不同的应用程序

因为主机上存在不同的服务,从网络中获取的数据在进行向上交付时,在传输层就会提取出该数据对应的目的端口号,进而确定该数据应该交付给当前主机上的哪一个服务进程(应用层)。即一台主机上可以同时部署端口号不同的服务。

在这里插入图片描述

在TCP/IP协议中,用“源IP地址”,“源端口号”,“目的IP地址”,“目的端口号”,“协议号”这样一个五元组来标识一个通信。

举个例子,我们打开浏览器用不同的页面访问CSDN,虽然源IP地址是一样的,但是源端口号不同,就表示两个不同的通信。通过这个五元组,服务器就能准确的区分请求从哪里来的

  • 通信流程

1️⃣ 先提取出数据当中的目的IP地址和目的端口号,确定该数据是发送给当前服务进程的。
2️⃣ 然后提取出数据当中的协议号,为该数据提供对应类型的服务。
3️⃣ 最后提取出数据当中的源IP地址和源端口号,将其作为响应数据的目的IP地址和目的端口号,将响应结果发送给对应的客户端进程。

2.2 端口号范围划分

端口号的长度是16位,因此端口号的范围是0 ~ 65535:

0 ~ 1023:知名端口号。比如HTTP,FTP,SSH等这些广为使用的应用层协议,它们的端口号都是固定的。(类比120或110)
1024 ~ 65535:操作系统动态分配的端口号。客户端程序的端口号就是由操作系统从这个范围分配的。

扫描二维码关注公众号,回复: 16004792 查看本文章

2.3 知名端口号

有些服务器是非常常用的,这些服务器的端口号一般都是固定的:

ssh服务器——22端口。
ftp服务器——21端口。
telnet服务器——23端口。
http服务器——80端口。
https服务器——443端口。

  • 查看端口号

可以vim /etc/services文件,该文件是记录网络服务名和它们对应使用的端口号及协议。
在这里插入图片描述

2.4 绑定端口号数目问题

  • 一个端口号是否可以被多个进程绑定?

不行! 因为端口号的作用就是标识唯一的一个进程。如果绑定了多个进程怎么找到对应的进程呢?所以如果绑定一个已经被绑定的端口号,就会出现绑定失败的问题。

  • 一个进程能不能绑定多个端口号?

可以! 比方说绑定了两个端口号A和B,这两个端口号标识的是同一个进程 ,这与端口号用来标识进程的唯一性不冲突。

2.5 pidof & netstat命令

  • pidof命令

查看进程的pid

在这里插入图片描述
配合kill杀死一个进程:
在这里插入图片描述
这里的xargs是用来把从管道读取的数据拼接到kill -9的后边。

  • netstat命令

用来查看网络状态

选项:

n:拒绝显示别名,能显示数字的全部转换成数字。
l:仅列出处于LISTEN(监听)状态的服务。
p:显示建立相关链接的程序名。
t(tcp):仅显示tcp相关的选项。
u(udp):仅显示udp相关的选项。
a(all):显示所有的选项,默认不显示LISTEN相关。

查看TCP相关的网络信息时,一般选择使用nltp组合选项。
在这里插入图片描述
查看UDP相关的网络信息时,一般选择使用nlup组合选项。
在这里插入图片描述

三、UDP协议

3.1 UDP协议格式

在这里插入图片描述

16位源端口号:表示数据从哪里来。
16位目的端口号:表示数据要到哪里去。
16位UDP长度:表示整个数据报(UDP首部+UDP数据)的长度。
16位UDP检验和:如果UDP报文的检验和出错,就会直接将报文丢弃。

我们在用户层使用端口一直用的是uint16_t,其根本原因就是因为传输层协议当中的端口号就是16位的。我们send数据并不是直接发送到网络里,而是发给了传输层。

  • 如何将报头和有效载荷分离?

UDP采用的是固定报头,UDP的报头当中只包含四个字段,每个字段的长度都是16位,总共8字节。所以直接提取前八个字节就是报头,其他的就是有效载荷。

  • UDP如何分用?(有效载荷交给上层的哪一个协议?)

应用层每个进程都绑定有端口号,UDP就是通过报头当中的目的端口号来找到对应的应用层进程的,把有效载荷交出去。

3.2 如何理解报头?

其实这里的报头就是一种结构化数据对象:

struct udp_hdr
{
    
    
    uint16_t src_port;// 源端口
    uint16_t dsc_port;// 目的端口
    uint16_t length;// UDP长度
    uint16_t check;// 校验和
};
  • UDP数据封装过程:

首先要知道应用层sendto数据是发给传输层的。

在这里插入图片描述
创建一块内存,计算出有效载荷的起始地址,拷贝有效载荷,强转填写报头部分。最后形成UDP报文。

  • UDP数据分用过程:

因为是定长报头,直接取出目的端口号,把有效载荷向上交付给指定协议(进程)。

3.3 UDP协议的特点

无连接:知道对端的IP和端口号就直接进行数据传输,不需要建立连接。
不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。
面向数据报:保证能读到完整的报文。

  • 面向数据报

这里就像快递一样,别人发了三个快递,那么我们一定要收到三个,不会收到一个,一个半。如果只有一个包裹,我们也不能只拿走一半。
发送了一个报文,要么不读,要么recvfrom等到读取完一整个报文返回。

如果发送端调用一次sendto,发送100字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节;而不能循环调用10次recvfrom,每次接收10个字节。

3.4 UDP缓冲区

1️⃣ UDP没有真正意义的发送缓冲区,因为它没有可靠机制,不需要把数据暂存起来。它直接把数据拷贝到内核,由内核将数据传给网络层协议进行后续的传输动作。
2️⃣ UDP是有接收缓冲区的,但是不能保证收到的顺序就是发送的顺序。而且如果缓冲区满了,再来的UDP数据就会被丢弃

而UDP在读的过程中也能写,所以是全双工的。

  • 为什么UDP要有缓冲区?

如果UDP没有接收缓冲区,那么就要求上层及时将UDP获取到的报文读取上去,如果一个报文在UDP没有被读取,那么此时UDP从底层获取上来的报文数据就会被迫丢弃。

3.5 UDP传输最大长度

UDP协议报头当中的UDP最大长度是16位的,因此一个UDP报文的最大长度是64K(包含UDP报头的大小)。

如果要传输大于64k的数据,就需要在应用层进行手动分包,多次发送,并在接收端进行手动拼装。

猜你喜欢

转载自blog.csdn.net/qq_66314292/article/details/131690626