当前位置: 首页 > news >正文

Linux网络:UDP

文章目录

  • 1. 传输层
  • 2. 端口
  • 3. UDP
    • 3.1 UDP报文
    • 3.2 UDP特点
    • 3.3 UDP应用场景
    • 3.4 Linux UDP接口

1. 传输层

tcp/ip协议栈中,应用层之下是传输层。

传输层中的很多行为都是内核帮我们完成,但是用户程序中也要调用一些接口进行设置。

传输层的协议有两个:UDP和TCP

本篇博客中介绍UDP.

2. 端口

端口本质上是一个unsigned short类型的无符号短整数,范围是0~65535
在tcp/ip协议中,端口号作为源IP,源端口,目的IP,目的端口,协议号中的重要组成部分,共同标识一个通信。

IP用于定位具体的机器,而端口用于定位到这台机器上的具体进程。

关于进程和端口的关系,一般来说,一个进程可以绑定多个端口,但是一个端口只能被一个进程绑定,对于后者,在没有对socket进行额外设置时,是正确的,但如果设置了某些属性,情况会有所不同。

自己的程序有些端口号是不能绑定的,通常内核也不会允许我们绑定,这些端口号是知名端口号,对应了一些知名应用层协议——即使用这些协议访问服务器时,访问的服务器端口号已经确定了。

3. UDP

3.1 UDP报文

在这里插入图片描述
上图是UDP的报文结构。
其中,源端口号和目的端口号,这些不必多说。

16位UDP长度表示整个UDP报文的长度,可见,UDP报文的最大长度是65535字节,这个长度包括报头(报头总共8字节)和有效载荷,如果超过这个长度,那么对于有效载荷,就需要在应用层手动分包。

16位UDP检验和,这个数据可用于验证该UDP报文在网络传输的过程中,内容是否发生更改。
检验和有其自身计算逻辑,发送端在发送时计算一次,接收端在接收时计算一次,二者进行比对,即可确认内容是否改变。

3.2 UDP特点

UDP网络通信有三个最大特点:无连接,不可靠,面向数据报。

什么是无连接呢?
相对于TCP,UDP网络通信,通信双方完全没有建立连接的机制,即便UDP使用connect,本质上无连接,只不过将对端IP和端口记录到内核中,后续通信接口由使用sendto/recvfrom,改为使用send/recv罢了。

什么是不可靠呢?
UDP网络通信没有确认应答机制,即接收端是否正常受到UDP报文,发送端是无法得知的。
UDP网络通信没有超时重传机制,用户层写入的发送数据,封装为UDP报文后,永远只会发送一次。
同时,UDP通信中,由于实际网络问题,先发送的UDP报文,可能后到达,而UDP内核中并不会维护这个顺序,谁先到就都谁,而实际上这个信息可能是后发的,并不是最先应该读取的信息。
而由于UDP是无连接,不维护连接状态,所以即便通信的一方彻底关闭,另一方也不会有任何感知,读写行为仍照旧,只不过此时通信已没有任何意义。

什么是面向数据报呢?
面向数据报是指UDP报文有明确的数据边界。TCP报文是字节流传输的,一次写入的数据可能被分批发送,也可能和一些其它数据一起发送,读取时,可能一次性无法读到完整数据,需要多次读取。 但UDP不一样,UDP报文发送,要么完整,要么不发送;UDP报文读取,要么不读,读就读到完整的UDP报文

因此,UDP报文明确的数据边界,使得UDP网络通信时,不需要在用户层处理粘包问题

3.3 UDP应用场景

性质决定用途,UDP无连接,不可靠,面向数据报的性质,使得UDP的应用场景如何呢?

UDP不用维护连接,网络通信不可靠,即不需要维护超时重传,确认应答等各种复杂机制,这就使得UDP在不考虑通信质量的情况下,通信效率是非常高的。

因此,对于那些对通信效率要求高,即实时性要求高,而允许一定程度的通信数据丢失场景下,UDP应用非常多,比如实时视频通话,或者网络直播等等。

除了上述场景外,在简单的网络通信场景中,比如DNS域名解析场景,总共就一问一答,非常简单,使用UDP即可,不必使用TCP,否则反倒因为TCP复杂机制,带来不必要的额外消耗。

3.4 Linux UDP接口

网络通信接口使用分为客户端和服务端。

客户端:

  1. 使用socket创建用于通信的网络套接字,返回相应文件描述符。
int fd = socket(AF_INET,SOCK_DGRAM,0);//指定协议号为0,让内核自动判别即可
  1. 客户端一般不显式绑定,而是在sendto发送数据时,由内核完成绑定。
  2. 使用sendto进行数据发送。
size_t n = sendto(fd,buffer,len,0,(struct sockaddr*)dest_addr,addrlen);//一般flag标志位给0即可,取默认情况
  1. 使用recvfrom进行数据接收。
size_t n = recvfrom(fd,buffer,len,0,(struct sockaddr*)src_addr,&addrlen);//注意这里的addrlen是取地址,因为要实际拿到写入src_addr的字节数

服务端:

  1. 使用socket创建网络套接字进行通信,与客户端相同。
  2. 服务端必须使用bind显式绑定。
int ret = bind(sockfd,addr,addrlen)

那么在第二个参数,即类型为struct sockaddr这个结构体中,我们需要手动填入什么呢?
在网络通信中,实际使用的是struct sockaddr_in这个类型,传参时需要做类型转化。
在这个结构体中,我们需要初始化三个变量:sin_family初始化为AF_INET,表示是网络通信,使用IpV4;sin_addr对应的是ip地址,需要使用相关接口进行主机字节序到网络大端字节序的转换sin_port对应的是具体端口,与ip地址相同,需用相关接口完成字节序的转换。

  1. 服务端使用recvfrom接收数据,接口和参数均同上。
  2. 服务端使用sendto发送数据,接口和参数也同上。
    服务端使用sendto发送数据时,可能会有疑惑:服务端如何知道客户端的IP+PORT呢?这本质上是逻辑顺序的问题。因为,客户端和服务端之间的通信,通常都是客户端已知服务端IP+PORT,然后客户端先给服务端发信息,此时服务端通过recvfrom的相关参数,即可得到客户端地址,然后再向此地址客户端发送消息,而客户端虽然未主动bind,但在sendto中,已经由内核自动bind,因此也能正常接收服务端消息。自此,双端通信的逻辑就是完善的。
http://www.dtcms.com/a/507131.html

相关文章:

  • vue3知识点-ref和reactive以及toRefs与toRef
  • 环保网站 源码wordpress展示页
  • NSSCTF - Web | 【第五空间 2021】pklovecloud
  • 了解“网络协议”
  • ECharts 实时数据平滑更新实践(含 WebSocket 模拟)
  • ImmutableList.of() 是 Google Guava 库 提供的一个静态工厂方法,用于创建一个不可变的(immutable)列表。
  • 【计算机网络】408考研计算机网络精讲:物理层核心——信道的极限容量(奈氏准则与香农定理)​​
  • 嵌入式模组拨号获取IP地址时,设置的ippass是什么原理,起到什么作用?
  • 网站开发 实训 报告郑州高端建站公司
  • 2025年--Lc203- 1218. 最长定差子序列(动态规划)--Java版
  • TDengine
  • 【MicroPython编程-ESP32篇】-L298N控制直流电机
  • C# 设计模式——单例模式
  • 单例模式与线程池的实际应用
  • Ubuntu24 逻辑卷磁盘扩容全流程
  • 网站加载速度慢的原因佛山网站建设公司价格
  • 容器化与调度:使用 Docker 与 K8s 管理分布式淘宝商品数据采集任务
  • 微服务熔断降级方案对比:Hystrix、Resilience4j与Sentinel实践
  • 解决在windows中基于Spring AI 集成文件管理MCP服务遇到的问题
  • 【研究生随笔】PyTorch中的概率论
  • 青少年活动中心网站建设依据青岛标志设计公司
  • 网站三要素关键词 描述怎么做网站建设报价单 excel
  • Kubernetes Pod 管理全攻略:从基础操作到进阶优化
  • 基于 OpenHarmony 6.0 的智能充电桩技术方案与实现
  • 三步破局:一致性轨迹强化学习开启扩散语言模型“又快又好”推理新时代
  • Node.js | pnpm下载安装与环境配置
  • 递归-二叉树中的深搜-2331.计算布尔二叉树的值-力扣(LeetCode)
  • 下部刚刚是上部
  • 自动化产线效率低,主要看这四个环节
  • 如何查询网站开发语言杭州企业网站制作