『 Linux 』网络传输层 - UDP

文章目录

    • UDP协议格式
    • UDP报头与有效载荷的分离
    • UDP报文交付上层
    • 16位UDP校验和
    • UDP协议特性
    • UDP协议的缓冲区
    • UDP报头结构化数据
    • 基于UDP的应用层协议
    • 端口号
    • Linux下常用的网络工具


UDP协议格式

当客户端向服务端使用UDP协议发送消息时,当数据来到传输层时系统会默认为数据添加一层UDP报头;

报头内容包括:

  • 16位源端口号

    该数据报来自哪个端口;

  • 16位目的端口号

    该数据报的目标端口;

  • 16位UDP长度

    该位置标明UDP报文的长度(包括数据正文部分);

  • 16位UDP检验和

    用于校验数据的完整性和正确性;


UDP报头与有效载荷的分离

UDP报头与有效载荷的分离采用的方式是通过订场报头进行的;

在UDP的报头中存在 16位UDP长度 ,该字段用来表明该报文的整体长度;

定长报头指的是UDP的报头具有固定长度,无论是哪一端所发送的UDP报文其报头的长度都是8Byte长度;

当一端接收到来自另一端的UDP报文时将对前8Byte逐步分析并读取UDP头部,当获取到对应的 16位UDP长度 后使用该长度减去对应的定长报头8Byte大小即得到数据正文的大小;

以这样的方式可以使得一个UDP报文进行对应的报头与有效载荷的分离也能使得接收方判断该报文的具体大小位置从而方便进行处理;


UDP报文交付上层

当接收方接收到UDP报文后,在进行报头与有效载荷分离后对应的报文需要交给传输层的上层,如软件层;

而将报文交付给上层时需要通过对应的端口号;

在UDP报头中存在两个用于识别来者身份和目标位置的两组头部信息,分别为 16位源端口号16位目的端口号 ;

其中 16位目的端口号 标志着接收方需要将UDP报文向上交付至哪个对应的进程;

在进行网络通信时进行网络通信的进程必须要绑定对应的端口号,且端口号具有唯一性,即一个在进行网络通信的进程可以绑定多个端口号,但是一个端口号只能被一个进程绑定,所以通过 16位目的端口号 可以准确让接收方知道该UDP报文需要被移交到上层的哪个进程;

以客户端向服务器发出UDP报文为例,其中 16位源端口号 信息在UDP报文形成时对应的进程在发送UDP报文时会默认随机绑定一个端口,在随机绑定端口后对应的 16位源端口号 信息也会被填充,而对于 16位目的端口号 信息而言,其通常为服务端的端口信息,通常一个知名的服务端的端口信息必须被客户端所知;


16位UDP校验和

在UDP报头字段中,存在 16位UDP校验和 字段,该字段是接收方用来检验UDP报文是否完整的一个字段;

UDP校验和是对伪首部,UDP头部,UDP数据的16位字进行按位求和(复合的累加和),再对求和的结果取反得出的;

其中伪首部(Pseudo Header)不是真正UDP数据的一部分,但在计算校验和时需要包括在内,伪首部包括源IP地址,目的IP地址,协议号(在IPv4中为17,表示UDP协议),UDP长度;

当接收方接收到UDP报文将对报文进行校验来确保报文是否完整:

  • 把伪首部,UDP头部和数据部分分为16位的字
  • 所有的16位字按位求和
  • 如果和的结果超过16位就将高位部分加到低位部分直至最终结果为一个16位的值
  • 对16位的累加和取反(即按位求补)得到最终的校验和值

UDP协议是无连接协议,不提供可靠的传输,但发送方仍然可以选择生成这个校验和来帮助接收方检测数据传输过程中可能出现的错误,使得接收方能明确表明所接收的UDP报文是否需要丢弃;


UDP协议特性

UDP(用户数据报协议)是一个简单的传输层协议,提供了无连接和不保证可靠性的通信方式,它有以下几点特性:

  • 数据报独立性

    UDP将每个传输单元称为数据报,每个数据报是一个独立的,完整的消息;

    数据报是自包含的,即包含了发送端和接收端的信息,每个数据报作为一个单独的实体进行传输;

    这些数据报之间没有任何关系,接收方无法知道他们的顺序和依赖关系;

  • 无连接性

    在发送之前不需要建立连接;

    UDP发送的数据报是直接发送到网络之中的,且数据报独立传输;

  • 不保证消息顺序和完整性

    数据报可能会丢失,重复或者乱序到达,但UDP协议不提供重传,消息确认或者重排序等机制;

    这意味着接收方的应用程序将自行处理这些问题;

  • 全双工

    UDP的socket既能读,也能写,这个概念叫做 全双工 ;

UDP的数据报独立性与TCP是不同的,TCP是面向字节流的传输,即TCP协议需要自行解决所接收数据是否为一个完整的数据,其与UDP不同,假设发送端给接收端发送了一个100Byte大小的数据,若是接收端接收到了,那么该数据报的大小必然是100Byte,而使用TCP协议时接收方的上层需要自行判断所接受的一个或是若干数据段是否为完整的报文;


UDP协议的缓冲区

实际上UDP没有真正意义上的发送缓冲区,当发送方使用UDP协议并使用sendto将数据进行发生后数据将直接将数据报发送至网络进行传输;

虽然UDP没有发送缓冲区但是其具有接受缓冲区;

接收缓冲区是任何端都必须必备的,因为不同的主机其对数据的处理能力是不同的,UDP协议需要接收缓冲区的主要原因是需要兼顾接收方对数据的处理能力,以防止接收方由于对数据的处理不及时而导致的大量数据丢包;

接收缓冲区可以让接收应用有更多的时间从缓冲区中读取数据从而缓解因数据处理不及时导致的大量丢包;

尽管UDP协议是有接收缓冲区的,但是毕竟缓冲区也是一块固定大小的内存,也会有缓冲区溢满的情况;

当接收缓冲区已满但接收方还未将缓冲区中的数据处理完毕时发送方再次向接收方发送UDP报文时对应的因为接收缓冲区已满,该报文会直接被丢弃;

同时接收缓冲区也无法保证所接收到的UDP报文的顺序和发送UDP报的顺序一致;


UDP报头结构化数据

通常情况现在所使用的Linux系统基本是使用C语言实现的,这意味着UDP协议作为系统的传输层也是使用C语言来编写的;

而实际上UDP的报头是一组结构化数据,即C语言的结构体来实现的;

主要包括以下字段:

  • 源端口号(16位)

  • 目的端口号(16位)

  • 长度(16位)

    整个UDP数据报的字节长度,包括头部和数据;

  • 校验和(16位)

    用于检测头部和数据中的错误;

下面是一个结构体示例来示例UDP报头的描述:

struct udp_header {
    uint16_t source_port : 16;  // 源端口号
    uint16_t dest_port : 16;    // 目的端口号
    uint16_t length : 16;       // 数据报长度
    uint16_t checksum : 16;     // 校验和
};

其中这种类型被称为位段类型;

位段类型也是一种自定义类型,在协议中该位段类型被称为UDP报头;

当UDP协议对报文添加报头时只需要定义对应的变量申请内存空间并把对应数据进行填充即可;

当使用UDP协议发送消息时只需要定义对应的UDP报头变量,将报头结构体变量进行填充,最后将报头与报文数据部分进行直接组合后即可调用sendto()将UDP报文发送至网络;

通常情况下,无论是发送方还是接收方,机器中必定会存在大量的UDP报文,发送方的机器中不同的UDP报文可能是不同进程发送的,而接收方的UDP报文可能是由不同的发送端向该端进行发送的,那么当机器中存在大量相同类型的数据时系统必然要对该类数据进行管理维护;

其管理维护的方式即为 “先描述,再组织” ;

所以通常系统中将会存在用来描述UDP报文的内核结构体,这种结构体被称为sk_buff

该结构体是Linux内核中用来描述网络数据包的核心数据结构,不仅包含了数据包的内容,还包括一些辅助信息,例如数据包的长度,网络接口,协议类型等;

struct sk_buff {
    struct sk_buff *next;       // 链表指针,指向下一个buffer
    struct sk_buff *prev;       // 链表指针,指向上一个buffer
    struct net_device *dev;     // 接口设备
    unsigned char *head;        // 数据缓冲区的开始指针
    unsigned char *data;        // 数据指针
    unsigned char *tail;        // 数据末尾指针
    unsigned char *end;         // 缓冲区的末尾指针
    unsigned int len;           // 数据长度
    unsigned int data_len;      // 数据区长度
    unsigned int truesize;      // 实际大小
    void *destructor;           // 释放内存的销毁函数
    // 省略了一些其他字段
};

这是一个简化的sk_buff结构体示例;

当系统中存在一个对应的UDP报文时对应的在该报文的某个固定位置将会附上该sk_buff结构体;

其中对应的sk_buff结构体中存在相同类型的指针用来指向其他的sk_buff对象;

通过以类似链表的方式将多个UDP报文进行管理;

当一段UDP报文被处理完成后对应的该整段内存将被释放;


基于UDP的应用层协议

基于UDP的应用层协议有如下:

  • DNS(域名解析)

    用于将域名解析为IP地址;

  • DHCP(动态主机配置协议)

    用于动态分配IP地址及其他网络配置;

  • TFTP(简单文件传输协议)

    用于基本文件传输操作;

  • SNMP(简单网络管理协议)

    用于网络设备的管理;

  • RIP(路由信息协议)

    用于网络路由信息的交换;

  • NTP(网络时间协议)

    用于时间同步;

  • VpIP(IP语音协议,如SIP,RIP)

    用于互联网语音传输;

  • STUN(简单穿透UDP穿越)

    用于网络地址转换穿透;


端口号

通常情况下需要进行网络通信的进程都需要绑定对应的端口号,无论是接收方还是发送方;

通常情况下对于客户端(无论是TCP协议还是UDP协议),其在进行发送时都不需要显式去绑定端口号;

而对于接收方而言(一般为服务端),其需要主动绑定一个端口号,且这个主动绑定的端口号是必须公开的;

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

当一个主机接收到了一个数据包时对应需要根据数据包中的端口号来将对应数据包中的数据传递给最终需要接收数据的进程;

在TCP/IP协议中,用"源IP",“源端口号”,“目标IP”,“目标端口号”,"协议号"这样的五元组来标示一个通信(可通过netstat -n查看);

  • 源IP地址

    发送数据包的一方的IP地址;

  • 目的IP地址

    接收数据报的一方的IP地址;

  • 源端口号

    发送方使用的端口号,通常是一个动态端口;

  • 目的端口号

    接收方使用的端口号,用于表示接收服务或者应用(如HTTP的80端口);

  • 协议类型

    使用的传输层协议,例如TCP(值为6)或UDP(值为17);

五元组的作用在于唯一标识一个网络连接或者是数据流,无论在建立一个TCP连接还是处理一个UDP数据报,五元组都起到的关键作用,每个数据包传输时都包含这些信息,使得接收方可以正确将数据包路由和传递到对应的应用程序;

端口号通常分为知名端口和动态分配端口:

  • 知名端口

    通常0-1023范围的端口号为知名端口号;

    下面是一些较为常用的知名端口;

    端口号 服务 协议 描述
    20 FTP Data TCP/UDP 文件传输协议(FTP)的数据传输通道
    21 FTP Control TCP/UDP 文件传输协议(FTP)的控制通道
    22 SSH TCP/UDP 安全外壳协议(SSH),用于安全登录和数据传输
    23 Telnet TCP Telnet协议,用于不安全的远程登录
    25 SMTP TCP 简单邮件传输协议(SMTP),用于电子邮件传输
    43 WHOIS TCP WHOIS协议,用于查询注册用户信息
    53 DNS TCP/UDP 域名系统(DNS),用于域名解析
    67 DHCP Server UDP 动态主机配置协议(DHCP),服务器端
    68 DHCP Client UDP 动态主机配置协议(DHCP),客户端
    69 TFTP UDP 简单文件传输协议(TFTP)
    80 HTTP TCP 超文本传输协议(HTTP),用于网页访问
    110 POP3 TCP 邮局协议版本3(POP3),用于接收电子邮件
    119 NNTP TCP 网络新闻传输协议(NNTP),用于网络新闻组
    123 NTP UDP 网络时间协议(NTP),用于时间同步
    143 IMAP TCP Internet消息访问协议(IMAP),用于接收电子邮件
    161 SNMP UDP 简单网络管理协议(SNMP)
    194 IRC TCP/UDP Internet中继聊天(IRC)协议
    443 HTTPS TCP HTTP Secure(HTTPS),用于加密的网页访问
    445 Microsoft-DS TCP/UDP 用于微软的DS服务(常用于SMB/CIFS文件共享)
    465 SMTPS TCP 使用SSL的简单邮件传输协议(SMTP)
    514 Syslog UDP 系统日志协议(Syslog)
    636 LDAPS TCP/UDP 轻量级目录访问协议(LDAP)安全版本
    873 Rsync TCP Rsync协议,用于文件同步和传输
    990 FTPS TCP 使用SSL的FTP协议
    993 IMAPS TCP 使用SSL的IMAP协议
    995 POP3S TCP 使用SSL的POP3协议
    1433 MS SQL Server TCP 微软SQL Server数据库的默认端口
    1521 Oracle DB TCP Oracle数据库的默认端口
    2049 NFS TCP/UDP 网络文件系统(NFS)的默认端口
    3306 MySQL TCP MySQL数据库的默认端口
    3389 RDP TCP 远程桌面协议(RDP),用于远程桌面访问
    5432 PostgreSQL TCP PostgreSQL数据库的默认端口
    6379 Redis TCP Redis数据库的默认端口

    通常情况也可以通过cat /etc/services命令来查看当前机器所记录的知名端口号;

  • 动态分配端口

    即在发送数据包时发送端动态绑定的端口即为操作系统动态分配端口;


Linux下常用的网络工具

  • netstat

    netstat工具是一个用来查看网络状态的重要工具;

    其语法通常为netstat [select],即netstat后跟上选项,常用的选项为如下:

    • -n

      拒绝显示别名,能显示数字的转化为数字;

    • -l

      仅列出有在Listen监听状态的服务状态;

    • -p

      显示建立相关链接的程序名;

    • -t

      仅显示TCP相关选项;

    • -u

      仅显示UDP相关选项;

    • -a

      显示所有选项,默认不显示LISTEN监听相关;

  • pidof

    该工具可以查看服务器的进程id;

    语法为pidof [process name],即pidof后跟进程名或服务名;

    通过进程名或者服务名来查看对应进程的进程ID;

上一篇:海螺 2.27.1 |AI生成视频 AI音乐 语音通话


下一篇:3.1 机器学习--线性回归