「网络编程」传输层协议_ UDP协议学习_及原理深入理解

「前言」文章内容大致是传输层协议,UDP协议讲解。

「归属专栏」网络编程

「主页链接」个人主页

「笔者」枫叶先生(fy)

UDP

目录

  • 一、传输层
  • 二、UDP协议
    • 2.1 再谈端口号
      • 2.2.1 端口号范围划分
      • 2.2.2 认识知名端口号
      • 2.2.3 端口号注意问题
      • 2.2.4 netstat命令和pidof命令
    • 2.2 UDP协议格式
    • 2.3 UDP的特点
    • 2.4 UDP的缓冲区
    • 2.5 UDP注意事项
    • 2.6 基于UDP的应用层协议

一、传输层

HTTP协议普通用户认为是将请求和响应直接发送到了网络当中。但实际应用层需要先将数据交给传输层,由传输层对数据做进一步处理后再将数据继续向下进行交付,该过程贯穿整个网络协议栈,最终才能将数据发送到网络当中

传输层负责在网络中提供可靠的数据传输服务。它主要解决了主机之间的通信问题。

常见的传输层协议有TCP(传输控制协议)和UDP(用户数据报协议),传输层已经是操作系统内核部分了
在这里插入图片描述
下面学习的是UDP协议,TCP在下一篇。

二、UDP协议

2.1 再谈端口号

重谈概念

端口号是在传输层中使用的一个标识符,用于识别不同的应用程序或服务。它是一个16位的整数(2字节),范围从0到65535

  • 端口号的组合由IP地址和端口号一起构成了一个套接字(Socket),用于唯一标识网络中的通信终点。
  • 在传输层的通信中,源主机使用源端口号,目标主机使用目标端口号,以便正确地将数据传输到相应的应用程序或服务。
  • 通过使用不同的端口号,传输层可以实现多个应用程序同时进行通信,保证数据的正确传输和接收。

端口号的作用

  • 端口号(Port)标识一个主机上进行网络通信的不同的应用程序,即标识主机上进程的唯一性
  • 从网络中获取的数据在进行向上交付时,在传输层就会提取出该数据对应的目的端口号,进而确定该数据应该交付给当前主机上的哪一个服务进程
  • 即在传输层协议的报头当中就会包含与端口相关的字段

在这里插入图片描述
这些概念在套接字篇章都谈过了,不再赘述

五元组

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

在这里插入图片描述

比如有多台客户端主机同时访问服务器,这些客户端主机上可能有一个客户端进程,也可能有多个客户端进程,它们都在访问同一台服务器。

而这台服务器就是通过“源IP地址”,“源端口号”,“目的IP地址”,“目的端口号”,“协议号”来识别一个通信的。
在这里插入图片描述

2.2.1 端口号范围划分

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

  • 已知端口号(Well-known Ports)是指被分配给特定服务或协议的端口号,范围从0到1023
  • 动态端口号(Dynamic Ports)是指在使用过程中临时分配给应用程序的端口号,范围从1024到65535。
  • 0 ~ 1023:知名(已知)端口号。比如HTTP,FTP,SSH等这些广为使用的应用层协议,它们的端口号都是固定的。
  • 1024 ~ 65535:操作系统动态分配的端口号。客户端程序的端口号就是由操作系统从这个范围分配的。

2.2.2 认识知名端口号

有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:

  • ssh服务器,使用22端口。
  • ftp服务器,使用21端口。
  • telnet服务器,使用23端口。
  • http服务器,使用80端口。
  • https服务器,使用443端口。

查看知名端口号:

vim /etc/services

在这里插入图片描述
我们自己写一个程序使用端口号时,要避开这些知名端口号

2.2.3 端口号注意问题

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

  • 一个进程可以绑定多个端口号。这与“端口号必须唯一标识一个进程”是不冲突的
  • 在某些情况下,一个进程可能需要同时提供多个服务或协议,或者需要同时监听多个端口来处理不同类型的数据

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

  • 一个端口号通常只能被一个进程绑定(%99的情况下都是)。每个端口号在一个特定的时间点只能由一个进程使用,以确保数据的正确传输和接收
  • 如果绑定一个已经被绑定的端口号,就会出现绑定失败的问题

2.2.4 netstat命令和pidof命令

netstat命令

netstat是一个用于显示网络连接、路由表和网络接口信息的命令

netstat英文全称:network statistics网络统计

常用选项:

  • -a:all (显示所有连接和监听端口)
  • -t:tcp (仅显示TCP连接)
  • -u:udp (仅显示UDP连接)
  • -n:numeric (以数字形式显示IP地址和端口号)
  • -p:program (显示与连接关联的进程信息)
  • -l:listen(仅列出有在 Listen (监听) 的服务状态)
  • -r:route (显示路由表信息)
  • -s:statistics (显示网络统计信息)

命令演示

查看TCP相关的网络信息时,一般选择使用-nltp组合选项。

netstat -nltp

在这里插入图片描述

查看UDP相关的网络信息时,一般选择使用-lnup组合选项。

netstat -lunp

在这里插入图片描述

pidof命令

pidof命令是一个用于查找正在运行的进程的命令。它可以通过进程名来查找与之匹配的进程的进程ID(PID),比较方便

语法: pidof [进程名]
功能:通过进程名,查看进程id

命令演示

在这里插入图片描述
可以组合使用

pidof test | xargs kill -9

注:xargs是一个用于构建和执行命令行的实用程序。它从标准输入中读取数据,并将其作为参数传递给指定的命令
在这里插入图片描述

2.2 UDP协议格式

UDP协议格式如下:
在这里插入图片描述
前8个字节是UDP的报头,报头包括:

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

数据部分(用户数据)可有可无,数据部分就是有效载荷

UDP如何将报头与有效载荷进行分离?

UDP的报头已经规定大小,即UDP采用定长报头,UDP在读取报文时读取完前8个字节后剩下的就都是有效载荷

UDP如何决定将有效载荷交付给上层的哪一个协议?

  • UDP是通过报头当中的目的端口号来找到对应的应用层进程的,即由目的端口号决定。
  • 当UDP数据报到达时,操作系统会根据目的端口号找到相应的应用程序或服务,并将数据报交付给它进行处理

理解协议的报头

Linux内核是用C语言写的,UDP/TCP协议处于内核中,所以所谓的报头就是一种结构化的数据对象

比如UDP,下图左边是位段写法
在这里插入图片描述

数据封装:

以UDP为例,应用层将数据交给传输层时,传输层会创建一个UDP报头,并填充报头中的各个字段,包括源端口号和目的端口号等信息。然后,操作系统会在内核中开辟一块空间,将UDP报头和有效载荷(即应用层数据)拷贝到一起,形成UDP报文
在这里插入图片描述

分用

以UDP为例,当传输层从下层获取到一个报文后,就会读取该报文的前8个字节,提取出对应的目的端口号。通过目的端口号找到对应的上层应用层进程,然后将剩下的有效载荷向上交付给该应用层进程
在这里插入图片描述

2.3 UDP的特点

UDP传输的过程就类似于寄信,其特点如下:

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

无连接,在套接字代码已经体现到了(与TCP相比),不解释;不可靠学了TCP就懂了

下面解释一下数据报

面向数据报

  • 应用层交付给UDP多长的报文,UDP就原样发送,既不会拆分,也不会合并,这就叫做面向数据报。
  • 可以想像成快递:你朋友给你发了1个快递,你就只能收1个快递,你不能只收0.5个快递,也不能收2个快递,你只能收1个,即发多少就收多少。对比读数据
  • UDP发送的数据不能太大,UDP的报文最大长度是64KB(UDP首部+UDP数据)
  • 如果超过 64KB了,必须进行拆分,拆分的每个小数据都必需比64KB小,这个是应用层写代码自己做的工作。如果超了,就发不了
  • 比如用UDP传输100个字节的数据,发送端调用一次发送函数,发送100字节,那么接收端也必须调用对应的一次接收函数,接收100个字节;如果发送端调用十次发送函数,则接收端也必须调用对应的十次接收函数,即UDP协议,发送函数的次数 : 接收函数的次数 = 1 : 1

2.4 UDP的缓冲区

  • UDP没有真正意义上的发送缓冲区。调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
  • UDP具有接收缓冲区。但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃。

缓冲区以TCP为例

发送接收数据:

  • 发送函数(write等)在自己的应用层有自己的应用层发送缓冲区,调用发送函数实际上是把数据拷贝到传输层的发送缓冲区中
  • 数据是否发送到网络中,由TCP协议自主决定,所以TCP协议称为传输控制协议,关键字:传输控制
  • 接收函数(read等)在自己的应用层也有自己的应用层接收缓冲区,调用接收函数实际上是把传输层接受缓冲区中数据拷贝到自己应用层接收缓冲区中
  • 所以read、write、send、recv、sendto等函数本质上是拷贝函数
  • 一方在发送,另一方也在发送,双方根本就不会影响,因为它们有成对的缓冲区,一个负责发送,一个负责接收,所以TCP是全双工的
  • 这对缓冲区有生产消费模型的思想,兼具该模型的优点

在这里插入图片描述

为什么UDP没有发送缓冲区

  • 因为不需要,UDP协议的设计目标是提供一种简单的、无连接的通信方式。
  • UDP协议的设计初衷是为了实现高效的数据传输,尽量减少协议本身的开销。
  • UDP协议并不提供可靠性和流量控制的机制,因此不需要发送缓冲区
  • 调用sendto会把数据直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。

为什么UDP要有接收缓冲区?

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

注意:UDP接收缓冲区满了,再来报文直接丢弃

UDP需要有接收缓冲区是为了应对网络传输中的不可靠性和不确定性。

因为UDP本身是不可靠的,所以接收方可能会面临以下情况:

  • 数据到达的速度快于应用程序的处理速度:如果接收方的应用程序无法及时处理到达的数据报,那么接收缓冲区可以暂时存储这些数据,避免数据丢失。
  • 数据到达的顺序可能不同于发送顺序:由于UDP的无连接性,数据报可能以不同的顺序到达接收方。接收缓冲区可以暂时存储这些乱序的数据报,并按照应用程序的需要进行排序和组装。
  • 网络拥塞或丢包:在网络传输中,可能会发生丢包或拥塞的情况。接收缓冲区可以缓冲部分数据,以便在网络恢复正常后重新接收丢失的数据。

虽然UDP没有发送缓冲区,但是UDP的socket既能读,也能写,所以也是全双工

2.5 UDP注意事项

上面已经谈过了

  • 需要注意的是,UDP协议报头当中的UDP最大长度是16位的,因此一个UDP报文的最大长度是64K(包含UDP报头的大小)。
  • 然而64K在当今的互联网环境下,是一个非常小的数字。如果需要传输的数据超过64K,就需要在应用层进行手动分包,多次发送,并在接收端进行手动拼装。

2.6 基于UDP的应用层协议

  • NFS:网络文件系统。
  • TFTP:简单文件传输协议。
  • DHCP:动态主机配置协议。
  • BOOTP:启动协议(用于无盘设备启动)。
  • DNS:域名解析协议。

--------------------- END ----------------------

「 作者 」 枫叶先生
「 更新 」 2023.7.18
「 声明 」 余之才疏学浅,故所撰文疏漏难免,或有谬误或不准确之处,敬请读者批评指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/28559.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之享元模式

写在前面 本文看下一种结构型设计模式,享元模式。 1:介绍 1.1:什么时候使用享元模式 当程序需要大量的重复对象,并且这些大量的重复对象只有部分属性不相同,其他都是相同的时候,就可以考虑使用享元设计…

STM32之按键驱动的使用和自定义(MultiButton)

原始Github地址 Github地址 修改后 调整内容 将宏定义转换成配置结构体 头文件 #ifndef _MULTI_BUTTON_H_ #define _MULTI_BUTTON_H_#include "stdint.h" #include "string.h"//According to your need to modify the constants. //#define TICKS_IN…

Redis实战案例19-Redis解决主从一致性问题

主节点(Master)“写操作”: 接收并响应客户端的读写请求。持久化数据到磁盘(根据配置可以选择使用RDB快照或者AOF日志)。将自己的写操作同步给所有的从节点。处理发布/订阅(Pub/Sub)模式中的发…

AUTOSAR CP标准的RTE和BSW各模块的设计及开发工作

AUTOSAR(Automotive Open System Architecture)是一种开放的汽车电子系统架构标准,旨在提供一种统一的软件架构,以实现汽车电子系统的模块化和可重用性。 AUTOSAR标准中的两个重要模块是RTE(Runtime Environment&…

微服务Day2——Nacos注册中心入门

Nacos注册中心 1、Nacos简介 国内公司一般都推崇阿里巴巴的技术,比如注册中心,SpringCloudAlibaba也推出了一个名为Nacos的注册中心。 2、Mac安装 进入Nacos官网下载安装包 http://nacos.io/zh-cn/ Github仓库地址 下载解压后进入nacos/bin目录下 …

Docker——认识Docker 常用命令 Linux中安装docker 常见问题及其解决

目录 引出Docker是啥?Docker是啥?Docker VS 虚拟机1.特性优势2.资源优势 Docker的架构Docker常用命令(0)docker run(1)docker ps(2)docker stop 容器名称(3)…

大二毕设.2-自研Spring框架

目录 项目描述: 基本演示 提取标记类 IOC容器的装载 IOC容器的操作 DI依赖注入 Aspect排序 AOP MVC 功能实现讲解 项目描述: 为了更好地学习 Spring 的核心,参考 Spring 源码实现的一个简易框架当前已实现 IOC,DI依赖注…

学习react,复制一个civitai(C站)-更新3

更新内容 优化了一下加载速度 图片列表 初步更新了199张图片,大部分都有stable diffusion 的prompts。 可以直接复制到AI绘画里面使用。 先来看看效果图吧: 我还是挺喜欢这种砌砖流布局 技术点 同样使用了砌墙瀑布流布局:masonry js 安装方法 npm …

2023-07-10 linux IIO子系统使用学习,在TI 的ads1015驱动里面看到相关使用,故花点时间进行简单的学习,入门级别,纪录点滴。

一、Linux IIO(Industrial I/O)架构是Linux内核提供的一种用于支持各种类型传感器和数据采集设备的子系统,包括温度、压力、湿度、加速度、光度等多种传感器。 二、这个就是ads1015的驱动,里面用到iio子系统。 ti-ads1015.c adc…

qiankun框架vue3主应用和子应用生产环境打包部署nginx

首先下载nginx,进行最小化配置 用vscode 打开nginx.conf文件 在http模块的server模块里进行配置 listen 字段监听端口号 http的默认端口号是80(nginx的端口号可以随便写) server_name字段 是ip地址 lochhost就是127.0.0.1 lacation 字段 是在浏览器的地址栏http协议ip地址…

【es报错】:

报错信息 reasonrequest [/test1] contains unrecognized parameter: [include_type_name] 解决方法 统一导入client下的包:

Leetcode-每日一题【1019.链表中的下一个更大结点】

题目 给定一个长度为 n 的链表 head 对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。 返回一个整数数组 answer ,其中 answer[…