day-04 基于UDP的服务器端/客户端
一.理解UDP
(一)UDP套接字的特点
UDP套接字具有以下特点:
-
无连接性:UDP是一种无连接的协议,这意味着在发送数据之前,不需要在发送方和接收方之间建立连接。每个UDP数据包都是独立的,它们可以独立地发送和接收,而不需要维护连接状态。
-
不可靠性:UDP是一种不可靠的协议,这意味着它不提供数据传输的可靠性保证。UDP数据包在发送过程中可能会丢失、重复、乱序或损坏,而UDP协议本身不提供任何机制来检测和纠正这些问题。因此,应用程序需要自行处理这些问题。
-
高效性:由于UDP不需要建立连接和维护连接状态,它的开销比TCP更小,传输效率更高。UDP适用于那些对实时性要求较高,但对数据可靠性要求相对较低的应用场景,如音频和视频流传输。
-
面向数据报:UDP是一种面向数据报的协议,每个UDP数据包都是一个独立的数据报,具有固定的大小。UDP数据包的大小限制为64KB,超过这个大小的数据需要进行分片和重新组装。
-
支持多播和广播:UDP支持多播和广播功能,可以将数据同时发送给多个接收方。多播是一种一对多的通信方式,广播是一种一对所有的通信方式。
总的来说,UDP套接字具有无连接性、不可靠性、高效性、面向数据报和支持多播和广播等特点。它适用于那些对实时性要求较高,但对数据可靠性要求相对较低的应用场景。
(二)UDP内部工作原理
UDP的内部工作原理如下:
-
创建套接字:在UDP通信之前,需要创建UDP套接字。套接字是一个网络通信的端点,用于发送和接收数据。通过调用操作系统提供的套接字API,可以创建一个UDP套接字。
-
绑定端口:在创建UDP套接字后,需要将套接字绑定到一个特定的端口上。这样,其他应用程序就可以通过指定该端口来与UDP套接字进行通信。
-
发送数据:要发送数据,应用程序将数据写入UDP套接字的发送缓冲区。操作系统将从发送缓冲区中获取数据,并将其封装成UDP数据包。然后,操作系统将UDP数据包发送到目标IP地址和端口。
-
接收数据:要接收数据,应用程序需要监听UDP套接字。当有UDP数据包到达时,操作系统将从网络中接收数据包,并将其放入UDP套接字的接收缓冲区。应用程序可以从接收缓冲区中读取数据。
-
处理数据:应用程序可以从接收缓冲区中读取数据,并对数据进行处理。由于UDP是无连接的协议,每个UDP数据包都是独立的,应用程序需要自行处理数据包的顺序、丢失、重复和损坏等问题。
-
关闭套接字:当UDP通信结束时,应用程序可以关闭UDP套接字,释放相关资源。
总的来说,UDP的内部工作原理涉及创建套接字、绑定端口、发送数据、接收数据和处理数据等步骤。UDP是一种简单的协议,不提供连接状态维护和可靠性保证,但具有较低的开销和较高的传输效率。
(三)UDP的高效使用
要高效使用UDP,可以考虑以下几点:
-
数据包大小:UDP数据包的大小限制为64KB,超过这个大小的数据需要进行分片和重新组装。为了提高传输效率,可以尽量减小数据包的大小,避免数据分片和重新组装的开销。
-
数据压缩:对于需要传输的数据,可以考虑使用数据压缩算法进行压缩,减小数据包的大小。常见的数据压缩算法包括gzip、zlib等。
-
并发处理:UDP是无连接的协议,每个UDP数据包都是独立的。为了提高处理效率,可以使用多线程或多进程的方式,并发处理接收到的UDP数据包。
-
丢包处理:由于UDP是不可靠的协议,数据包在传输过程中可能会丢失。为了提高可靠性,可以在应用层实现丢包检测和重传机制。例如,可以使用序列号和确认应答的方式来检测丢包,并进行重传。
-
超时设置:为了避免数据包长时间滞留在网络中,可以设置合适的超时时间。如果在超时时间内没有收到对应的确认应答,可以进行重传。
-
流量控制:为了避免发送方发送过多的数据导致接收方无法及时处理,可以实现流量控制机制。例如,可以使用滑动窗口的方式控制发送方的发送速率。
-
多播和广播:UDP支持多播和广播功能,可以将数据同时发送给多个接收方。通过合理使用多播和广播,可以提高数据传输的效率。
总的来说,要高效使用UDP,可以考虑数据包大小、数据压缩、并发处理、丢包处理、超时设置、流量控制和多播/广播等方面的优化策略。根据具体的应用场景和需求,可以选择适合的优化方法。
二.实现基于UDP的服务器端/客户端
1.UDP中的服务器端和客户端没有连接
2.UDP服务器端和客户端均只需一个套接字
3.基于UDP的数据I/O函数
基于UDP的数据I/O函数通常使用以下两个函数:
1.sendto()
:该函数用于向指定的目标地址发送UDP数据包。它的函数原型如下:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
参数说明:
sockfd
:UDP套接字的文件描述符。buf
:要发送的数据的指针。len
:要发送的数据的字节数。flags
:发送标志,通常设置为0。dest_addr
:目标地址的结构体指针,包括IP地址和端口号。addrlen
:目标地址结构体的长度。
该函数将指定的数据发送到目标地址。如果发送成功,返回发送的字节数;如果发送失败,返回-1,并设置相应的错误码。
2.recvfrom()
:该函数用于从指定的源地址接收UDP数据包。它的函数原型如下:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数说明:
sockfd
:UDP套接字的文件描述符。buf
:接收数据的缓冲区指针。len
:接收数据的最大字节数。flags
:接收标志,通常设置为0。src_addr
:源地址的结构体指针,用于存储发送方的IP地址和端口号。addrlen
:源地址结构体的长度。
该函数从指定的UDP套接字接收数据,并将数据存储到指定的缓冲区中。如果接收成功,返回接收的字节数;如果接收失败,返回-1,并设置相应的错误码。
4.基于UDP的回声服务器端/客户端
uecho_server.cpp
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUFFER_SIZE 1024int main() {// 创建UDP套接字int server_socket = socket(AF_INET, SOCK_DGRAM, 0);// 绑定服务器地址和端口struct sockaddr_in server_address{};server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = htonl(INADDR_ANY);server_address.sin_port = htons(8888);bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));std::cout << "服务器已启动,等待客户端连接..." << std::endl;while (true) {// 接收数据char buffer[BUFFER_SIZE];struct sockaddr_in client_address{};socklen_t client_address_length = sizeof(client_address);ssize_t received_bytes = recvfrom(server_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_address, &client_address_length);buffer[received_bytes] = '\0';std::cout << "接收到来自客户端 " << inet_ntoa(client_address.sin_addr) << " 的数据:" << buffer << std::endl;// 发送数据回客户端sendto(server_socket, buffer, strlen(buffer), 0, (struct sockaddr*)&client_address, client_address_length);}return 0;
}
uecho_client.cpp
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUFFER_SIZE 1024int main() {// 创建UDP套接字int client_socket = socket(AF_INET, SOCK_DGRAM, 0);// 服务器地址和端口struct sockaddr_in server_address{};server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = inet_addr("127.0.0.1");server_address.sin_port = htons(8888);while (true) {// 输入要发送的数据char message[BUFFER_SIZE];std::cout << "请输入要发送的数据:";std::cin.getline(message, BUFFER_SIZE);// 发送数据到服务器sendto(client_socket, message, strlen(message), 0, (struct sockaddr*)&server_address, sizeof(server_address));// 接收服务器返回的数据char buffer[BUFFER_SIZE];socklen_t server_address_length = sizeof(server_address);ssize_t received_bytes = recvfrom(client_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&server_address, &server_address_length);buffer[received_bytes] = '\0';std::cout << "接收到服务器返回的数据:" << buffer << std::endl;}return 0;
}
5.UDP的数据传输特性和调用connect函数
UDP存在数据边界,所以调用几次 sendto 函数去发送,就调用几次 recvfrom 函数去接收。
(1)已连接(connected)UDP套接字和未连接(unconnected)UDP套接字
sendto 函数的传输阶段
- 向UDP套接字注册目标IP和端口号
- 传输数据
- 删除UDP套接字中注册的目标地址信息
UDP套接字默认属于未连接套接字。但在对同一主机进行通信时,过多的增删套接字中目标地址信息,很明显显得多余。所以将UDP套接字变成已连接套接字会提高效率。
相关文章:

day-04 基于UDP的服务器端/客户端
一.理解UDP (一)UDP套接字的特点 UDP套接字具有以下特点: 无连接性:UDP是一种无连接的协议,这意味着在发送数据之前,不需要在发送方和接收方之间建立连接。每个UDP数据包都是独立的,它们可以独…...
FFmpeg rtp rtp_mpegts的区别
rtp 在FFmpeg中,rtpenc是一个用于将音视频数据封装成RTP(Real-time Transport Protocol)数据包并发送到网络上的编码器。RTP是一种用于实时传输音视频数据的协议,常用于视频会议、流媒体等场景。 rtpenc可以将音视频数据封装成R…...

【链表OJ】相交链表 环形链表1
前言: 💥🎈个人主页:Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 一.leetcode 160. 相交链表 1.问题描述: 2.解题思路: 二.leetcode 141.环形链表 …...

DevOps之自动化测试
什么是自动化测试? 明确一下自动化测试不是什么。自动化测试不是指自动化生成测试代码,而是自动化地执行由开发人员或测试人员编写的测试代码。正如下面这句谚语:“绝不要手工去做任何可以被自动化处理的事情。——Curt Hibbs” 之前是由人…...

Java 程序打印 OpenCV 的版本
我们可以使用 Java 程序来使用 OpenCV。 OpenCV 的使用需要动态库的加载才可以。 加载动态库 到 OpenCV 的官方网站上下载最新的发布版本。 Windows 下载的是一个可执行文件,没关系,这个可执行文件是一个自解压程序。 当你运行以后会提示你进行解压。…...

ChatGPT⼊门到精通(2):ChatGPT 能为我们做什么
⼀、雇佣免费的⼲活⼩弟 有了ChatGPT后,就好⽐你有了好⼏个帮你免费打⼯的「⼩弟」,他们可以帮你做很多 ⼯作。我简单总结⼀些我⽬前使⽤过的⽐较好的基于ChatGPT的服务和应⽤。 1、总结、分析 当我们在阅读⼀些⽂章和新闻的时候,有的⽂章写…...
线程和进程的区别是什么?
线程(Thread)和进程(Process)是操作系统中两个重要的概念,用于管理程序的执行。它们有以下区别: 定义:进程:进程是程序的一个执行实例,它包含了程序的代码、数据以及执行上下文。进程是操作系统分配资源和调度的基本单位。线程:线程是进程的子执行单元,一个进程可以…...
力扣27.移除元素
27. 移除元素 提示 简单 1.9K 相关企业 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序…...

指针(个人学习笔记黑马学习)
1、指针的定义和使用 #include <iostream> using namespace std;int main() {int a 10;int* p;p &a;cout << "a的地址为:" << &a << endl;cout << "a的地址为:" << p << endl;…...
vue 路由动态加载
在 Vue.js 中,可以使用 webpack 的动态导入语法来实现路由动态加载。下面是一个简单的示例: const Home () > import(/* webpackChunkName: "home" */ ./views/Home.vue); const About () > import(/* webpackChunkName: "about…...

电脑识别不了固态硬盘怎么办?
在使用固态硬盘时,可能会出现电脑无法识别的情况,这时我们就无法使用固态硬盘中的数据。那么,电脑识别不了固态硬盘怎么办? 为什么电脑识别不了固态硬盘? 一般来说,电脑识别不了固态硬盘是因为以下3个原因…...
QCustomPlot 绘制卡顿问题
大数据量导致曲线绘制卡顿问题 这里提供一个思路在跟踪源码中发现底层卡顿在vector的resize() 此处扩容中 所以尽量使用下面的接口 /*! \overloadAdds the provided data point as \a key and \a value to the current data.Alternatively, you can also access and modify t…...

uni-app开发小程序,radio单选按钮,点击可以选中,再次点击可以取消
一、实现效果: 二、代码实现: 不适用官方的change方法,自己定义点击方法。 动态判断定义的值是否等于遍历的值进行回显,如果和上一次点击的值一样,就把定义的值改为null <template><view><radio-group&…...

【Qt专栏】实现单例程序,禁止程序多开的几种方式
目录 一,简要介绍 二,实现示例(Windows) 1.使用系统级别的互斥机制 2.通过共享内存(进程间通信-IPC) 3.使用命名互斥锁(不推荐) 4.使用文件锁 5.通过网络端口检测 一…...
力扣26. 删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做…...
【机器学习】鸢尾花分类-逻辑回归示例
这段代码是一个完整的示例,展示了如何使用逻辑回归对鸢尾花数据集进行训练、保存模型,并允许用户输入数据进行预测。以下是对这段代码的总结:功能: 这段代码演示了如何使用逻辑回归对鸢尾花数据集进行训练,并将训练好的…...

Flink CDC介绍
1.CDC概述 CDC(Change Data Capture)是一种用于捕获和处理数据源中的变化的技术。它允许实时地监视数据库或数据流中发生的数据变动,并将这些变动抽取出来,以便进行进一步的处理和分析。 传统上,数据源的变化通常通过…...

Java集合sort排序报错UnsupportedOperationException处理
文章目录 报错场景排查解决UnmodifiableList类介绍 报错场景 我们使用的是PostgreSQL数据库,存储业务数据,业务代码使用的是Spring JPA我们做的是智慧交通信控平台,有个功能是查询展示区域的交通态势,需要按照不同维度排序展示区…...

安防监控/磁盘阵列存储/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?
安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,能对外分发RTSP、RT…...
Spring boot开启定时任务
Cron表达式生成器 基于接口的方式 使用Scheduled 注解很方便,但缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,那么可以使用接口来完成定时任务,统一将定时器信…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
Windows 下端口占用排查与释放全攻略
Windows 下端口占用排查与释放全攻略 在开发和运维过程中,经常会遇到端口被占用的问题(如 8080、3306 等常用端口)。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口,帮助你高效解决此类问题。 一、准…...