传输层——UDP

2024-05-24 08:36
文章标签 udp 传输层

本文主要是介绍传输层——UDP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在学习计算机网络的过程中,我们知道OSI七层协议模型,但是在实际开发应
用中我们发现OSI七层协议模型并不适合实施,因为OSI上三层通常都是由开
发人员统一完成的,这三层之间在实现过程中没有一个明确的界限,所以我
们更多的是将七层模型认为是TCP/IP四层协议(除去硬件层),而TCP、IP
分别是两个网络层中非常具有代表性的网络协议,其中TCP处于传输层。而
在传输层中除却TCP协议之外,还有一个很重要的协议那就是UDP协议,所
以,今天我们就来认识一下UDP协议是什么样的。

需要注意的是,本篇文章讲述的是UDP的较为底层的知识,默认读者已经会使用socket套接字的网络编程,以及UDP和TCP的简单认识。

1. 如何认识网络协议

关于对网络协议的比较简单的认识方法,可以看我的另一篇博客:应用层协议,无论是哪一层的网络协议,它们的认识方法都是大致相同的,那就是认识网络协议在计算机中做出的约定,也就是结构化字段。

2. UDP的结构化字段

在这里插入图片描述
在传输层中的报文我们一般叫做数据段。
在学习某一层的某一个网络协议时,我们都要明白,这个报文如何将报头和有效载荷分离,以及如何将有效载荷向上交付?
对于两台主机的网络通信,对于传输层,我们需要知道两台主机的IP地址、端口号、以及传输层协议,这样我们就可以使用IP地址定位到唯一一台主机,协议号知道传输层使用的是哪个协议(这个是IP层的事情),然后利用端口号定位到一台主机的唯一一个进程,我们就可以在网络上精准的与一台主机上的一个进程进行网络通信了,而我们将上面需要的两台主机的IP地址、端口号、以及协议号,称为一个五元组。
所以我们自然的就解决了UDP协议如何向上交付的问题,那就是利用目的端口号。
而对于报头和有效载荷的分离,我们发现UDP协议中有一个字段就是16位报文长度,这个表示了一个UDP报文的长度,而UDP报头长度是固定的八字节,所以我们向上交付有效载荷的时候只需要根据UDP报头做出偏移就可以,至此有效载荷与报头的分离也明了了。
可能有人还有问题,那就是在TCP协议是面向字节流的,作为面向字节流的协议,这意味着上层使用该协议的应用层往往需要自行确保自己收到的报文是完整的(这通常需要应用层协议的配合),而我们在使用UDP协议进行socket编程的时候,好像从来没注意过这个问题,我们直接使用sendto、recvfrom两个系统调用将数据拿上来,这个数据就是独立且完整的,这是因为UDP协议是面向数据报的,报文和报文之间有着明显的边界,所以我们才不需要对UDP报文单独做处理。
但是好像还是不对,无论你是那个协议在底层传输时不都是字节序吗,那有什么面向数据报,面向字节流的说法,凭什么UDP的报文就不需要考虑报文的完整性和独立性的问题?
所以我在这里给出结论:UDP协议也是要确保自己收到的报文是独立且完整的,但是这一点不需要用户来做,UDP协议会自行处理。说是UDP协议处理,UDP协议是内嵌在操作系统中的,UDP协议处理,不就是操作系统处理吗?
对于接收到的报文,UDP协议会检测它是否有八字节的报头长度,没有直接丢弃,反之根据16位报文长度来进行进一步报文的完整性的验证以及报文之间的分离。期间有任何一个条件不满足,直接将报文丢弃,这也就是UDP协议不可靠的主要原因。
在UDP的协议的结构化字段中,还有一个字段是16位检验和,这个是用来检验报文是否有问题的,我们不讨论。
而上面的结构化字段中端口号无论是目的端口号还是源端口号,大小都是16位,这也是为什么socket编程中,端口变量都是使用uint16_t而不是int。

3. UDP协议的进一步理解

在上面对UDP结构化字段的认识过程中,经常会提到 “报头” 这个字眼,我们也说学习某一层的某一个网络协议我们都需要研究它的结构化字段,也就是报文,而报文就是报头 + 有效载荷。有效载荷是用户的应用层数据,我们可以使用一个缓冲区来将它们存放起来,这个好理解,那么报头如何在计算机中理解呢?
其实报头在计算机中就是一个结构体:

struct udphdr
{uint16_t src_port; // 源端口号uint16_t des_port; // 目的端口号uint16_t length; // 报文长度uint16_t check; // 校验和
};

现在我们就需要意识到一个场景,我们的计算机中会不会同时存在大量的UDP报文?这个显然是会的,那么既然存在大量的UDP报文,就需要对这些报文进行管理,如何管理?先描述,再组织。
那么我们就可以描述一下这个报文:

struct sk_buff
{char* data;char* tail;sk_buff* prev;sk_buff* naxt;//...
};

其中如果有应用层协议向下交付了一个报文,我们需要使用UDP协议将这个有效载荷进行封装,我们可以这样封装:
在这里插入图片描述

我们先创建一个结构体sk_buff,此时我们需要让data指针向前移动有效载荷个大小,然后将应用层的数据拷到缓冲区中,再让data指针向前移动八字节,然后再放入UDP报头。这样我们就完成了报文的封装,我们的计算机中存在大量的UDP报文,我们的传输层中可能就是这样:

在这里插入图片描述

这样的话,对UDP报文的管理就转化为了对该链表的增删查改。
现在我们就明白了UDP协议的报文的管理以及报文的封装,现在我们将报文发出去了,如何接收呢?对端主机不是也遵守UDP协议吗?它也认识这个sk_buff啊,那么拿到有效载荷不是很自然吗?
而对于UDP的接收方,会将有效载荷存放在一个接收缓冲区中,UDP协议没有发送缓冲区,这一点与TCP协议是不同的:
在这里插入图片描述

UDP协议为什么需要接收缓冲区呢?这是因为没有接收缓冲区的话,上层应用来不及处理报文的话,继续来到的报文就直接被丢弃了,如果是这样的话UDP协议也太不靠谱了,怎么说也还是得靠谱一点。
那么为什么没有发送缓冲区呢?
这是因为UDP协议是不可靠的,而至于进一步的理解,则需要配合TCP协议来了解。

4. UDP协议知识的补充

在Linux源代码中我们可以找到上面提到的两个结构体:
在这里插入图片描述
在这里插入图片描述
UDP的特点:无连接,不可靠,面向数据报。
UDP没有发送缓冲区,只有接收缓冲区,如果接收缓冲区满了之后,继续接收到的报文会直接丢弃,直到接收缓冲区有多余空间。
这个接收缓冲区你可以理解为它就是一个队列,里面放的是交付上层的有效载荷。
UDP是全双工的,对于一个文件描述符,发的同时也可以收。
在使用UDP协议的时候需要注意发送的报文的大小不可以超过16位报文长度可表示的长度,不然多余的载荷会被丢弃。而16位能表示的大小在现如今是非常小的,只有65536字节,这也是它的局限性之一。
但是仍然有一些应用层协议使用的仍是UDP协议,这些应用层协议的特点就是传输的报文大小不会太大,以下是一些上层使用UDP协议的比较出名的应用层协议:
NFS: 网络文件系统
TFTP: 简单文件传输协议
DHCP: 动态主机配置协议
BOOTP: 启动协议(用于无盘设备启动)
DNS: 域名解析协议
以上就是我对UDP协议的一个较为深刻的理解。

这篇关于传输层——UDP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/997904

相关文章

[Spring Boot]Netty-UDP客户端

文章目录 简述Netty-UDP集成pom引入ClientHandler调用 消息发送与接收在线UDP服务系统调用 简述 最近在一些场景中需要使用UDP客户端进行,所以开始集成新的东西。本文集成了一个基于netty的SpringBoot的简单的应用场景。 Netty-UDP集成 pom引入 <!-- netty --><dependency><group

TCP与UDP_三次握手_四次挥手

TCP vs UDP TCP数据 具体可以通过Cisco Packet Tracer工具查看: UDP数据 三次握手、四次挥手 为什么是3/4次?这牵扯到单工、双工通信的问题 TCP建立连接:表白 TCP释放连接:分手 TCP—建立连接—三次握手 解释: 首先,启动服务器,让服务器进入监听状态(监听客户端的连接请求)。客户端向服务器发送同

iOS 网络相关面试题(一个基于UDP的简单的聊天Demo)

一、分别用C语言、python、GCDAsyncUdpSocket来实现UDP通信 1、C语言方式 首先初始化socket对象,Udp要用SOCK_DGRAM然后初始化sockaddr_in网络通信对象,如果作为服务端要绑定socket对象与通信链接,来接收消息然后开启一个循环,循环调用recvfrom来接收消息收到消息后,保存下发消息对象的地址,以便之后回复消息 - (void)init

面向连接的TCP和无连接的UDP

用户数据报协议UDP和传输控制协议TCP: 1.TCP传输的是TCP报文段,UDP传输的是UDP用户数据报。 2.UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后释放连接。TCP不提供广播或多播服务。由于T

UDP编程初识

复习: TCP     每个TCP套接字都有一个发送区,我们可以使用SO_SNDBUF来更改缓冲区的大小,当进程调用write时,内核从该应用进程的缓冲区中复制所有数据到套接字的缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据(或是应用进程的缓冲区大于套接字的发送缓冲区,或是套接字的发送缓冲区已有其他数据),该应用进程将被投入睡眠(这里的套接字是阻塞的),内核将不从write系统

板凳---------unix网络编程卷1:第二章传输层:TCP、UDP 和 SCTP

2.1 概述 焦点是传输层,包括TCP、UDP和SCTP(Stream Control Transmission Protocol,流控制传输协议)。绝大多数客户/服务器网络应用使用TCP或UDP。SCTP是一个较新的协议,最初设计用于跨因特网传输电话信令。这些传输协议都转而使用网络层协议IP:或是IPv4,或是IPv6。绕过传输层直接使用IPv4或IPv6,称为原始套接字。 UDP是一个简单的

java基础总结:(3)TCP和UDP通信

网络:一组相互连接的计算机,多台计算机组成,使用物理线路进行连接 网络编程的三要素:     【1】IP地址:唯一标识网络上的每一台计算机,两台计算机之间通信的必备有素     【2】端口号:计算机中应用的标号(代表一个应用程序)  0-1024系统使用或保留端口 ,  有效端口0-65536     【3】通信协议:通信的规则 TCP,UDP 网络模型一     OSI参考模式:开放系统互连

TCP 和 UDP 可以同时绑定相同的端口吗?

在网络编程中,TCP和UDP都可以绑定到同一个端口上进行通信。TCP和UDP是OSI模型中的传输层协议,它们分别使用不同的端口号来区分不同的应用程序或服务。 TCP(Transmission Control Protocol)提供了面向连接的、可靠的传输服务,它使用三次握手建立连接,并通过确认、重传、窗口控制等机制保证数据的可靠传输。 UDP(User Datagram Protocol)提供

网络编程(TCP协议,UDP协议)

目录 网络编程三要素 IP IPv4 InetAddress类 端口号 协议 UDP协议 UDP协议发送数据 UDP协议接收数据 UDP的三种通信方式(代码实现) TCP协议 TCP通信程序 三次握手和四次挥手  练习  1、客户端:多次发送数据服务器:接收多次接收数据,并打印 2、客户端:发送一条数据,接收服务端反馈的消息并打印 服务器:接收数据并打印,再给客户

java中UDP简单聊天程序

学过计算机网络通信的都知道,计算机之间传送数据由两种,即TCP通信和UDP通信。TCP是可靠的面向连接的通信协议,二UDP是不可靠的面向无连接的通信协议。   java中有基于TCP的网络套接字通信,也有基于UDP的用户数据报通信,UDP的信息传输速度快,但不可靠!   基于UDP通信的基本模式:  (1)将数据打包,称为数据包(好比将信件装入信封一样),然后将数据包发往目的地。  (