UDP编程流程(UDP客户端、服务器互发消息流程)

一、UDP编程流程

1.1、 UDP概述

UDP,即用户数据报协议,是一种面向无连接的传输层协议。相比于TCP协议,UDP具有以下特点:

  1. 速度较快:由于UDP不需要建立连接和进行复杂的握手过程,因此在传输数据时速度稍快于TCP协议。
  2. 适用于简单的请求/应答应用程序:对于一些简单的、对可靠性要求不高的应用程序,如DNS查询和SNMP请求,UDP能够提供高效的传输服务。
  3. 不适用于海量数据传输:由于UDP不提供可靠的数据传输机制,因此在进行大数据传输时容易出现丢包和乱序的情况,不建议使用UDP进行此类传输。
  4. 广播和多播应用必须使用UDP:UDP支持广播和多播传输,因此对于需要进行广播和多播的应用,如视频直播和组播通信,必须使用UDP协议。

UDP应用:

UDP协议被广泛应用于各种网络应用中,包括但不限于以下几种:

  • DNS(域名解析):DNS使用UDP进行域名解析请求和响应的传输,以提高查询速度。
  • NFS(网络文件系统):NFS使用UDP进行文件操作请求和响应的传输,以提高文件访问速度。
  • RTP(实时传输协议):RTP使用UDP进行实时音视频数据的传输,以减少延迟。

此外,一些实时性要求较高的应用,如在线游戏和VoIP通话,也会选择使用UDP协议来减少延迟,提高用户体验

1.2、网络编程接口socket

Socket,也被称为"套接字",是网络编程中用于实现不同主机上进程间通信的一种技术。它提供了一种将网络通信抽象为文件操作的接口,使得程序员可以通过简单的函数调用来实现复杂的网络通信功能。

Socket的特点

  1. 文件描述符:Socket是一种文件描述符,它代表了一个通信管道的端点。通过Socket,我们可以像操作文件一样,使用read、write、close等函数来发送和接收网络数据。
  2. 通信端点:Socket是网络通信的端点,每个Socket都有一个唯一的地址,通过这个地址,我们可以与远程主机上的Socket进行通信。
  3. 网络数据操作:通过Socket,我们可以方便地进行网络数据的发送和接收。Socket提供了丰富的函数接口,如send、recv、sendto、recvfrom等,用于各种网络数据操作。
  4. Socket函数:要获得一个Socket,我们需要调用socket()函数。该函数返回一个Socket描述符,用于后续的网络通信操作。

Socket的分类

根据使用的协议和通信方式的不同,Socket可以分为以下几种类型:

  • SOCK_STREAM:流式套接字,用于TCP协议。它提供了可靠的、面向连接的通信方式,数据以流的形式传输,可以保证数据的可靠性和顺序性。
  • SOCK_DGRAM:数据报套接字,用于UDP协议。它提供了不可靠、无连接的通信方式,数据以数据报的形式传输,不保证数据的可靠性和顺序性。
  • SOCK_RAW:原始套接字,用于其他层次的协议操作。它允许直接访问网络层数据,可以用于实现自定义的网络协议。

1.3 UDP编程C/S架构

UDP网络编程流程:

服务器: 创建套接字 socket( )

                将服务器的ip地址、端口号与套接字进行绑定 bind( )

                接收数据 recvfrom()

                发送数据 sendto()

客户端:  创建套接字 socket()

                发送数据 sendto()

                接收数据 recvfrom()

                关闭套接字 close() 

二、UDP编程-创建套接字 

2.1 创建socket套接字

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
功能:创建一个套接字,返回一个文件描述符
参数:domain:通信域,协议族AF_UNIX 本地通信AF_INET ipv4网络协议AF_INET6 ipv6网络协议AF_PACKET 底层接口
type:套接字的类型SOCK_STREAM 流式套接字(tcp)SOCK_DGRAM 数据报套接字(udp)SOCK_RAW 原始套接字(用于链路层)
protocol:附加协议,如果不需要,则设置为0
返回值:成功:文件描述符失败:-1

特点 

  •  创建套接字时,系统不会分配端口
  •  创建的套接字默认属性是主动的,即主动发起服务的请求;当作为服务器时,往往需要修改为被动的

 2.2举例创建套接字

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>int main(int argc, char const *argv[]) {// 使用socket函数创建套接字// 创建一个用于UDP网络编程的套接字int sockfd;if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {perror("fail to socket");exit(1);}printf("sockfd = %d\n", sockfd);return 0;
}

使用socket()函数创建了一个UDP类型的套接字,并打印出该套接字的文件描述符。如果创建套接字失败,则会输出错误信息并退出程序。

 执行结果

三、UDP编程-发送、绑定、接收数据 

3.1 IPv4套接字地址结构

在网络编程中经常使用的结构体

头文件:#include <netinet/in.h>

  struct in_addr{ in_addr_t s_addr;//ip地址 4字节};
struct sockaddr_in{sa_family_t sin_family;//协议族 2字节in_port_t sin_port;//端口号 2字节struct in_addr sin_addr;//ip地址 4字节char sin_zero[8]//填充,不起什么作用 8字节};

为了使不同格式地址能被传入套接字函数,地址须要强制转换成通用套接字地址结构,原因是因为不同场合所使用的结构体不一样,但是调用的函数却是同一个,所以定义一个通用结构体,当在指定场合使用时,在根据要求传入指定的结构体即可

通用结构体 sockaddr

头文件:#include 

struct sockaddr{ sa_family_t sa_family; // 2字节char sa_data[14] //14字节};

3.2 两种地址结构使用场合

在定义源地址和目的地址结构的时候,选用struct sockaddr_in;

struct  sockaddr_in  my_addr;

当调用编程接口函数,且该函数需要传入地址结构时需要用struct sockaddr进行强制转换

bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr));

3.3 发送数据—sendto函数 

#include <sys/types.h>
#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

功能: sendto函数用于通过套接字发送数据。

参数:

  • sockfd:文件描述符,由socket函数返回。
  • buf:指向要发送数据的缓冲区的指针。
  • len:要发送的数据的长度。
  • flags:标志位,用于指定发送操作的行为。常见的标志位有:
    • 0:阻塞模式,函数会一直等待直到数据发送完成。
    • MSG_DONTWAIT:非阻塞模式,如果数据不能立即发送,函数会立即返回错误。
  • dest_addr:指向目的网络信息结构体的指针,用于指定数据发送的目标地址。
  • addrlen:目的网络信息结构体的长度。

返回值:

  • 成功:返回发送的字节数。
  • 失败:返回-1,并设置errno以指示错误原因。

sendto函数是网络编程中常用的函数之一,它允许我们向指定的目标地址发送数据。在使用该函数时,我们需要正确地指定目的地址和地址长度,以确保数据能够准确地发送到目标。同时,我们也需要注意选择合适的标志位,以满足不同的发送需求。

 3.4 向“网络调试助手”发送消息

我们用一个“网络调试助手”的软件来模拟服务器,给服务器发送消息。

客户端的代码编写

#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h> #define N 128int main(int argc, char const *argv[])
{//./a.out 192.168.3.78 8080if(argc < 3){fprintf(stderr, "Usage:%s ip port\n", argv[0]);exit(1);}//第一步:创建套接字int sockfd;if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){perror("fail to socket");exit(1);}printf("sockfd = %d\n", sockfd);//第二步:填充服务器网络信息结构体 sockaddr_instruct sockaddr_in serveraddr;socklen_t addrlen = sizeof(serveraddr);serveraddr.sin_family = AF_INET; //协议族,AF_INET:ipv4网络协议serveraddr.sin_addr.s_addr = inet_addr(argv[1]); //ip地址serveraddr.sin_port = htons(atoi(argv[2]));//第三步:发送数据char buf[N] = "";while(1){fgets(buf, N, stdin);buf[strlen(buf) - 1] = '\0'; //把buf字符串中的\n转化为\0if(sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&serveraddr, addrlen) == -1){perror("fail to sendto");exit(1);}}//第四步:关闭套接字文件描述符close(sockfd);return 0;
}

执行结果 

 3.5 绑定--bind函数

UDP网络程序想要收取数据需什么条件?

确定的ip地址

确定的port

怎样完成上面的条件呢?

接收端 使用bind函数,来完成地址结构与socket套接字的绑定,这样ip、port就固定 了 发送端 在sendto函数中指定接收端的ip、port,就可以发送数据了

 由于服务器是被动的,客户端是主动的,所以一般先运行服务器,后运行客户端,所以服务 器需要固定自己的信息(ip地址和端口号),这样客户端才可以找到服务器并与之通信,但 是客户端一般不需要bind绑定,因为系统会自动给客户端分配ip地址和端口号

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:将套接字与网络信息结构体绑定
参数:sockfd:文件描述符,socket的返回值addr:网络信息结构体通用结构体(一般不用)struct sockaddr
网络信息结构体 sockaddr_in#include <netinet/in.h>
struct sockaddr_in
addrlen:addr的长度
返回值:成功:0失败:-1

3.6 bind示例

//第二步:将服务器的网络信息结构体绑定前进行填充
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
serveraddr.sin_port = htons(atoi(argv[2]));//第三步:将网络信息结构体与套接字绑定
if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
{perror("fail to bind");exit(1);
}

3.7 接收数据—recvfrom 函数

#include <sys/types.h>
#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
功能:接收数据
参数:sockfd:文件描述符,socket的返回值buf:保存接收的数据len:buf的长度flags:标志位0 阻塞MSG_DONTWAIT 非阻塞src_addr:源的网络信息结构体(自动填充,定义变量传参即可)addrlen:src_addr的长度返回值:成功:接收的字节数失败:-1

3.8 接收“网络调试助手”的数据

此时我们把刚刚也用到过的网络调试助手作为客户端,ubuntu的程序作为服务器

设置服务器(ubuntu程序) 

#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h> #define N 128int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s ip port\n", argv[0]);exit(1);}//第一步:创建套接字int sockfd;if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){perror("fail to socket");exit(1);}//第二步:将服务器的网络信息结构体绑定前进行填充struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]); //192.168.3.103serveraddr.sin_port = htons(atoi(argv[2])); //9999//第三步:将网络信息结构体与套接字绑定if(bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1){perror("fail to bind");exit(1);}//接收数据char buf[N] = "";struct sockaddr_in clientaddr;socklen_t addrlen = sizeof(struct sockaddr_in);while(1){if(recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&clientaddr, &addrlen) == -1){perror("fail to recvfrom");exit(1);}//打印数据//打印客户端的ip地址和端口号printf("ip:%s, port:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));//打印接收到数据printf("from client: %s\n", buf);}return 0;
}

执行结果

 四、UDP编程-client、server

接下来我们就可以自己实现服务器与客户端互发消息了

4.1 UDP客户端

1、本地IP、本地端口(我是谁)

2、目的IP、目的端口(发给谁)

3、在客户端的代码中,我们只设置了目的IP、目的端口

客户端的本地ip、本地port是我们调用sendto的时候linux系统底层自动给客户端分配 的;分配端口的方式为随机分配,即每次运行系统给的port不一样

//udp客户端的实现
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h>int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(1);}int sockfd; //文件描述符struct sockaddr_in serveraddr; //服务器网络信息结构体socklen_t addrlen = sizeof(serveraddr);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//客户端自己指定自己的ip地址和端口号,一般不需要,系统会自动分配#if 0struct sockaddr_in clientaddr;clientaddr.sin_family = AF_INET;clientaddr.sin_addr.s_addr = inet_addr(argv[3]); //客户端的ip地址clientaddr.sin_port = htons(atoi(argv[4])); //客户端的端口号if(bind(sockfd, (struct sockaddr *)&clientaddr, addrlen) < 0){perror("fail to bind");exit(1);}#endif//第二步:填充服务器网络信息结构体//inet_addr:将点分十进制字符串ip地址转化为整形数据//htons:将主机字节序转化为网络字节序//atoi:将数字型字符串转化为整形数据serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//第三步:进行通信char buf[32] = "";while(1){fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = '\0';if(sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){perror("fail to sendto");exit(1);}char text[32] = "";if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&serveraddr, &addrlen) < 0){perror("fail to recvfrom");exit(1);}printf("from server: %s\n", text);}//第四步:关闭文件描述符close(sockfd);return 0;
}

4.3 UDP服务器

1、服务器之所以要bind是因为它的本地port需要是固定,而不是随机的

2、服务器也可以主动地给客户端发送数据

3、客户端也可以用bind,这样客户端的本地端口就是固定的了,但一般不这样做

//udp服务器的实现
#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h>int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(1);}int sockfd; //文件描述符struct sockaddr_in serveraddr; //服务器网络信息结构体socklen_t addrlen = sizeof(serveraddr);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//第二步:填充服务器网络信息结构体//inet_addr:将点分十进制字符串ip地址转化为整形数据//htons:将主机字节序转化为网络字节序//atoi:将数字型字符串转化为整形数据serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));//第三步:将套接字与服务器网络信息结构体绑定if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){perror("fail to bind");exit(1);}while(1){//第四步:进行通信char text[32] = "";struct sockaddr_in clientaddr;if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&clientaddr, &addrlen) < 0){perror("fail to recvfrom");exit(1);}printf("[%s - %d]: %s\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), text);strcat(text, " *_*");if(sendto(sockfd, text, sizeof(text), 0, (struct sockaddr *)&clientaddr, addrlen) < 0){perror("fail to sendto");exit(1);}}//第四步:关闭文件描述符close(sockfd);return 0;
}

执行的结果

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

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

相关文章

Arcpy批量克里金插值报错

Arcpy批量克里金插值报错 文章目录 Arcpy批量克里金插值报错问题解决参考 问题 在进行实验的时候&#xff0c;Arcpy中批量进行克里金插值报错&#xff0c;主要就是在运行这个工具的时候&#xff0c;一直报错&#xff0c;改了很多参数也不行 ERROR 010079: 无法估算半变异函数…

MySQL商城数据库88张表结构(46—50)

46、消息队列表 CREATE TABLE dingchengyu消息队列表 (id int(11) NOT NULL AUTO_INCREMENT COMMENT 序号,userId int(11) DEFAULT NULL COMMENT 用户id,msgTtype tinyint(4) DEFAULT 0 COMMENT 消息类型,createTime datetime DEFAULT NULL COMMENT 创建时间,sendTime datetim…

LabVIEW自动剪板机控制系统

LabVIEW自动剪板机控制系统 随着工业自动化的快速发展&#xff0c;钣金加工行业面临着生产效率和加工精度的双重挑战。传统的手动或脚踏式剪板机已无法满足现代生产的高效率和高精度要求&#xff0c;因此&#xff0c;自动剪板机控制系统的研究与开发成为了行业发展的必然趋势。…

【深度学习】序列模型

深度学习&#xff08;Deep Learning&#xff09;是机器学习的一个分支领域&#xff1a;它是从数据中学习表示的一种新方法&#xff0c;强调从连续的层中进行学习&#xff0c;这些层对应于越来越有意义的表示。 1. 为什么选择序列模型&#xff1f; 循环神经网络&#xff08;RNN…

[嵌入式系统-63]:RT-Thread-内核:内核在不同CPU架构上的移植和不同硬件板BSP上的移植

目录 内核移植 1. CPU 架构移植&#xff1a;由CPU厂家提供 1.1 实现全局中断开关&#xff1a;汇编语言实现 &#xff08;1&#xff09;关闭全局中断 &#xff08;2&#xff09;打开全局中断 1.2 实现线程栈初始化 1.3 实现上下文切换 &#xff08;1&#xff09;实现 rt…

零代码编程:用Kimichat从PDF文件中批量提取图片

一个PDF文件中&#xff0c;有很多图片&#xff0c;想批量提取出来&#xff0c;可以借助kimi智能助手。 在借助kimi智能助手中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个网页爬取Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹…

基于深度学习检测恶意流量识别框架(80+特征/99%识别率)

基于深度学习检测恶意流量识别框架 目录 基于深度学习检测恶意流量识别框架简要示例a.检测攻击类别b.模型训练结果输出参数c.前端检测页面d.前端训练界面e.前端审计界面&#xff08;后续更新了&#xff09;f.前端自学习界面&#xff08;自学习模式转换&#xff09;f1.自学习模式…

数据结构与算法之经典排序算法

一、简单排序 在我们的程序中&#xff0c;排序是非常常见的一种需求&#xff0c;提供一些数据元素&#xff0c;把这些数据元素按照一定的规则进行排序。比如查询一些订单按照订单的日期进行排序&#xff0c;再比如查询一些商品&#xff0c;按照商品的价格进行排序等等。所以&a…

021、Python+fastapi,第一个Python项目走向第21步:ubuntu 24.04 docker 安装mysql8、redis(二)

系列文章目录 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 安装redis 我会以三种方式安装&#xff0c; 第一、直接最简单安装&#xff0c;适用于测试环境玩玩 第二、conf配置安装 第三、集群环境安装 一…

电脑崩溃了,之前备份的GHO文件怎么恢复到新硬盘?

前言 之前咱们说到用WinPE系统给电脑做一个GHO镜像备份&#xff0c;这个备份可以用于硬盘完全崩溃换盘的情况下使用。 那么这个GHO镜像文件怎么用呢&#xff1f; 咱们今天详细来讲讲&#xff01; 如果你的电脑系统硬盘崩溃了或者是坏掉了&#xff0c;那么就需要使用之前备份…

ElementUI从unpkg.com完整下载到本地的方法 - 解决unpkg.com不稳定的问题 - 自建镜像站 - 不想打包只想cdn一下

方法 方法1&#xff09;随便弄个文件夹&#xff0c;根据官网npm方法下载包&#xff0c;提取即可 npm i element-ui -S cd /node_modules/element-ui/ ls src 安装npm方法&#xff1a;https://nodejs.org/en 方法2&#xff09;不推荐 - 在github中搜索对应的库zip包&#xff0…

C++仿函数周边及包装器

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

Vue Vant 移动端如何禁止手机调起自带的输入键盘

前言 前不久在公司用Vue2开发了一个手机充值项目&#xff0c;键盘组件用的vant2的NumberKeyboard 数字键盘组件&#xff1b;上线后在IOS端只有一个vant数字键盘组件&#xff0c;但到了Android端&#xff0c;输入框一获取焦点不仅vant数字键盘弹出&#xff0c;连手机自带的键盘…

39 死锁

目录 1.死锁 2.线程同步 3.条件变量 4.案例 死锁 概念 死锁是指在一组进程中的各个进程均占有不会释放的资源&#xff0c;但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待状态 四个必要条件 互斥条件&#xff1a;一个资源每次只能被一个执行流使用 请求…

如何使用提示测试为LLMs构建单元测试?

原文地址&#xff1a;how-to-build-unit-tests-for-llms-using-prompt-testing 确保您的人工智能交付&#xff1a;快速测试完美生成应用程序的基本指南 2024 年 4 月 26 日 如果你曾经编写过软件&#xff0c;你就会知道测试是开发过程中必不可少的一部分。特别是单元测试&#…

设计模式——保护性暂停

同步模式之保护性暂停 文章目录 同步模式之保护性暂停定义实现应用带超时版 GuardedObject扩展——原理之join扩展——多任务版 GuardedObject 定义 即 Guarded Suspension&#xff0c;用在一个线程等待另一个线程的执行结果 要点 有一个结果需要从一个线程传递到另一个线程&…

【Linux】进程的控制①之进程创建与进程退出

目录 ​编辑 一 、进程的创建 1、fork函数 2.函数的返回值 ①return 可以返回两次&#xff0c;使得父子进程读到的id有两个值 ②写实拷贝&#xff0c;使得父子进程读到的值都对自身有意义 a.为什么要写实拷贝&#xff0c;而不是在创建子进程的时候直接就将空间给子进程开辟好&a…

Linux系统安装Redis7(详细版)

Linux系统安装Redis7 一、windows安装redis二、Linux安装Redis下载redis编辑redis7.conf文件启动redis-server服务如何关闭redis服务设置Redis开机自启动 一、windows安装redis Window 下安装 下载地址&#xff1a;https://github.com/dmajkic/redis/downloads 下载到的Redi…

【Qt之·控件·样式表】

系列文章目录 文章目录 前言一、Qt样式表的基础知识1.1 Qt样式表的定义和语法规则1.2 Qt样式表中的选择器和属性1.2.1 盒子模型1.2.2 border 1.3 Qt样式表中的伪类和伪元素 二、编写基本的Qt样式表2.1 在Qt应用程序中引入样式表文件的方式2.2 设置基本的背景色、字体样式等 三、…

MATLAB中功率谱密度计算pwelch函数使用详解

MATLAB中功率谱密度计算pwelch函数使用详解 目录 前言 一、pwelch函数简介 二、pwelch函数参数说明 三、pxx pwelch(x)示例 四、[pxx,f]pwelch(x,window,noverlap,nfft,fs)示例 四、[pxx,f] pwelch(x,window,noverlap,nfft,fs,freqrange,spectrumtype)示例 五、多通道功…