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

Socket编程(TCP/UDP详解)

前言:之前因为做项目和找实习没得空,计算机网络模块并没有写成博客,最近得闲了,把计算机网络模块博客补上。

目录

一,UDP编程

1)创建套接字

2)绑定端口号

3)发送与接收数据

4)UDP简单的发送数据和接收数据服务器

二,TCP编程

1)创建套接字

2)绑定端口号

3)使套接字进入监听状态

4)获取成功建立连接的的文件描述符和主机信息

5)发送与接收数据

6)连接其他主机

7)TCP简单的发送数据和接收数据服务器


scoket编程即套接字编程,是网络编程的基础,它允许两台或者多台计算机进行网络通信,这篇文章主要讲socket编程利用里面的TCP和UDP相关接口实现网络通信。

一,UDP编程

在udp编程里面,我们首先要创建一个套接字,也就是文件描述符。用来接收数据与发送数据,但注意,UDP为每一个套接字维护一个缓冲区,但是发送缓冲区是临时的、不可见的。这是为什么呢?UDP是面向无连接的,每次发送数据都是相对独立的,这允许我们可以使用临时的缓冲区,UCP数据发送完就不管任何事了,不会像TCP一样要确认对方收到,没收到还要进行重传等操作。不维护一个长久的缓冲区,也可以节省空间资源,使UDP变得轻量与高效。如果接收缓冲区设置成临时的那么数据到达后,如果应用程序没有及时读取可能出现丢失,那么如果一直等到读取完再销毁,一个套接字缓冲区可能接收很多主机的信息,可能接收缓冲区会频繁的创建,销毁,这会有很多不必要的开销。

1)创建套接字

第一个参数是网络通信协议,如IPV4或者IPV6等,具体参考下图

第二个参数是套接字的类型,使用什么方式通信,如数据报(UDP)或者字节流(TCP)等

返回值为-1代表创建失败,并设置错误码,大于0代表成功创建。

使用例子:

        //AF_INET代表IPV4协议格式,SOCK_DGRAM代表以UDP数据报形式发送,0代表选择IPV4和UDP的默认协议int fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;}

2)绑定端口号

在我的上一篇文章,我们以及明白绑定端口号加上IP才能确定互联网内的唯一一台主机,客户端可以不绑定端口号,这样子操作系统就会随机分配端口号,但是服务端不能这样,不然其他人无法主动连接服务端,因为其他人根本无法发现它,需要被别人第一次主动发现需要绑定端口号。现在我们来学习绑定端口号的接口。

scokfd就是我们前面使用socket接口创建的文件描述符。我们重点介绍接下来第二个参数,第三个参数是第二个参数的长度。

addr是结构体强转后得到的,它可以由IPV4结构体格式强转得到,也可以由IPV6格式强转得到,socketaddr_in是IPV4协议,socketaddr_un是IPV6协议。可以看下图理解

struct socketaddr里面的内容

struct socketaddr_in里面的内容

上图struct in_addr里面的内容

具体初始化和使用例子:

//IPV4结构体struct sockaddr_in _addr; //设置为IPV4协议_addr.sin_family=AF_INET;//端口号网络字节序_addr.sin_port=htons(PORT);//IP地址网络字节序,inet_addr函数将C风格字符串的IP地址形式转化成uint32_t的网络字节序类型_addr.sin_addr.s_addr=inet_addr(IP);//成功返回0,失败返回-1设置错误码,设置成功只能接收来自IP主机发送给PORT的信息int result=bind(fd,(struct sockaddr*)&_addr,(socklen_t)sizeof(_addr));if(result!=0){cout<<"绑定端口号失败"<<endl;}

3)发送与接收数据

发送数据,UDP协议使用的是sendto接口

socketfd就是套接字文件描述符,buf是发送的数据地址,len是发送数据的长度,flag是位图,使用|可以实现对发送的方法控制

  • 发送标志,可以是一个或多个标志的组合,用于修改 sendto 的行为。常见的标志包括:
    • MSG_CONFIRM:请求确认消息已被接收(某些实现可能不支持)。
    • MSG_DONTROUTE:避免路由,直接发送到本地接口。
    • MSG_DONTWAIT:非阻塞发送,如果操作会阻塞,则立即返回错误。
    • MSG_EOR:表示记录结束(对某些协议有意义)。
    • MSG_MORE:指示发送的数据是更大消息的一部分。

后面两个参数就不必多少,目标地址的信息和长度强转得来。最后成功返回发送数据的长度,失败返回-1,并设置错误码。

接收数据,UDP协议用的是recvfrom函数,

socketfd就是套接字文件描述符,buf是接收数据存放的地址,len是接收数据的最大长度,flag是位图,使用|可以实现对接收数据的方法控制

  • 接收标志,可以是一个或多个标志的组合,用于修改 recvfrom 的行为。常见的标志包括:
    • MSG_PEEK:查看数据而不从队列中删除它。
    • MSG_WAITALL:请求接收完整的消息(对于某些协议可能不适用)。
    • MSG_DONTWAIT:非阻塞接收,如果操作会阻塞,则立即返回错误。
    • MSG_TRUNC:即使数据被截断也继续接收(通常与 MSG_PEEK 一起使用)。
    • MSG_CTRUNC:如果控制消息被截断,则设置 msg_flags 的 MSG_CTRUNC 标志。

src_addr会返回发送数据的信息,如端口号,IP地址,addrlen是src_addr的长度。成功返回收到数据的长度,失败返回-1。

4)UDP简单的发送数据和接收数据服务器

中间可能有一个地方没讲清楚,bind函数不论接收,数据还是发送数据都最好设置,设置成功能接收你设置的主机发过来的特点端口号消息,sendto函数里面设置的是要发送给的人的IP和端口号。recvfrom函数里面的struct sockeaddr是接收消息的发送主机信息,方便你回信息和处理。

发送端

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include<unistd.h>#include <arpa/inet.h>#include <netinet/in.h>#include<iostream>using namespace std;#define PORT 8081//本地环回通信测试#define IP "127.0.0.1"int main(){//AF_INET代表IPV4协议格式,SOCK_DGRAM代表以UDP数据报形式发送,0代表选择IPV4和UDP的默认协议int fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;return -1;}//不绑定端口号,操作系统随机分配char msg[13]="hello world!";struct sockaddr_in _send; _send.sin_family=AF_INET;_send.sin_port=htons(8080);_send.sin_addr.s_addr=inet_addr(IP);//给地址为IP主机8080端口号发送消息int result=sendto(fd,(void*)msg,13,0,(struct sockaddr*)&_send,(socklen_t)sizeof(_send));if(result<0){cout<<"发送数据失败"<<endl;return -1;}close(fd);return 0;}

接收端

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include<unistd.h>#include <arpa/inet.h>#include <netinet/in.h>#include<iostream>using namespace std;#define PORT 8080int main(){//AF_INET代表IPV4协议格式,SOCK_DGRAM代表以UDP数据报形式发送,0代表选择IPV4和UDP的默认协议int fd=socket(AF_INET,SOCK_DGRAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;return -1;}//IPV4结构体struct sockaddr_in _addr; //设置为IPV4协议_addr.sin_family=AF_INET;//端口号网络字节序_addr.sin_port=htons(PORT);//接收所有主机的信息_addr.sin_addr.s_addr=INADDR_ANY;//成功返回0,失败返回-1设置错误码int result=bind(fd,(struct sockaddr*)&_addr,(socklen_t)sizeof(_addr));if(result!=0){cout<<"绑定端口号失败"<<endl;return -1;}char msg[20];struct sockaddr_in recv;//必须写,不能为空。socklen_t len=sizeof(recv);result=recvfrom(fd,(void*)msg,20,0,(struct sockaddr*)&recv,&len);if(result<0){cout<<"接收数据数据失败"<<endl;return -1;}for(int i=0;i<result;i++){cout<<msg[i];}close(fd);return 0;}

二,TCP编程

1)创建套接字

创建套接字,与UDP创建套接字相似,只要把SOCK_DGRAM改为SOCK_STREAM

        //SOCK_STREAM代表字节流,适用于TCPint fd=socket(AF_INET,SOCK_STREAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;return -1;}

2)绑定端口号

绑定端口号与UDP没有差别,就是接收来自指定的主机的连接请求,UDP是没有连接,需要发送消息时指定目的地址的。暂时简单理解就行。

struct sockaddr_in _addr; //设置为IPV4协议_addr.sin_family=AF_INET;//端口号网络字节序_addr.sin_port=htons(PORT);//IP地址网络字节序,inet_addr函数将C风格字符串的IP地址形式转化成uint32_t的网络字节序类型_addr.sin_addr.s_addr=inet_addr(IP);//成功返回0,失败返回-1设置错误码int result=bind(fd,(struct sockaddr*)&_addr,(socklen_t)sizeof(_addr));if(result!=0){cout<<"绑定端口号失败"<<endl;return -1;}

3)使套接字进入监听状态

在TCP编程里面,创建套接字后并不能直接使用,TCP套接字只用来接收来自其他主机的连接请求,UDP发送完数据就不管了,是无连接的,TCP是面向连接的,双方会建立一个连接,也就是会为两台主机间创建单独的文件描述符,并且进行管理,这个文件描述符只能用来双方通信,而UDP可以实现一个文件描述符也就是socket就向所有主机发送消息。只有将套接字变成监听状态才会接收来自其他主机的连接。

第一个参数无需多言,就是我们使用socket函数创建的套接字,backlog是允许同时与多少台主机建立连接,也就是同时创建多少个通信的文件描述符,成功返回0,失败返回-1,并设置错误码。

        //允许同时最大与三个主机建立连接result=listen(fd,3);if(result!=0){cout<<"套接字启动监听失败"<<endl;return -1;}

4)获取成功建立连接的的文件描述符和主机信息

套接字进入监听状态后,我们需要获得建立连接的文件描述符,这样基于文件描述符才能和建立连接的主机通信,我们使用accept函数获取建立连接的消息,一般使用一个while循环来获取得到的多个连接信息。

第一个参数是套接字,第二个参数是连接主机的信息,第三个是第二个参数的长度,方便区分类型。成功返回建立连接的文件描述符,失败返回-1,并设置错误码。

        while(1){//这里不对对方主机信息进行处理,设置为空int fd_net=accept(fd,NULL,NULL);if(fd_net==-1){cout<<"TCP连接失败"<<endl;return -1;}//进行处理,发送或者接收数据}

5)发送与接收数据

TCP可以使用UDP的sendto和recvfrom函数发送与接收数据,但一般不这么做,因为TCP以及建立连接了,每个连接文件描述符都只和一台主机通信,被唯一的四元组来标识的,这个四元组包括源IP地址、源端口号、目的IP地址和目的端口号。没必要使用这两个函数,这两个函数里面还需要包括目的主机地。一般使用send和write,read与recv。

flag常用标志

  1. MSG_DONTWAIT(或MSG_NONBLOCK)
    • 作用:允许非阻塞操作。如果套接字被设置为非阻塞模式,并且发送缓冲区已满,则send函数会立即返回,而不是阻塞等待缓冲区空间可用。
    • 返回值:在非阻塞模式下,如果发送缓冲区已满,send函数可能返回-1,并设置errnoEAGAINEWOULDBLOCK,表示资源暂时不可用。
  2. MSG_OOB(Out-of-Band Data)
    • 作用:发送带外数据。带外数据通常用于发送紧急数据,这些数据会被接收方优先处理。然而,并非所有协议都支持带外数据,且其使用方式可能因协议而异。
    • 限制MSG_OOB标志通常仅适用于流式套接字(如SOCK_STREAM),而不适用于数据报套接字(如SOCK_DGRAM)。
  3. MSG_DONTROUTE
    • 作用:勿将数据路由出本地网络。这个标志告诉系统不要通过网关或路由器发送数据,而只在本地网络上发送。然而,并非所有系统都支持这个标志,且其效果可能因系统而异。

成功返回发送数据大小,失败返回-1,设置错误码。

fd是文件描述符,也就是accept函数的返回值,buf被发送的数据,count是发送的大小。

flag常用标志

  1. MSG_PEEK
    • 作用:查看接收队列中的数据,但不从队列中移除它们。这允许调用者在不实际消耗数据的情况下检查是否有数据可读。
    • 使用场景:在需要多次读取同一份数据或检查数据是否到达时非常有用。
  2. MSG_WAITALL
    • 作用:阻塞调用,直到接收到指定长度的数据或连接关闭。然而,需要注意的是,并非所有系统都支持这个标志,且其行为可能因系统而异。
    • 使用场景:在需要确保接收到完整消息时非常有用,但应谨慎使用,因为它可能导致程序在数据不足时长时间阻塞。
  3. MSG_DONTWAIT(或MSG_NONBLOCK
    • 作用:在非阻塞模式下接收数据。如果当前没有数据可读,则立即返回,而不是阻塞等待。
    • 使用场景:在需要避免阻塞等待数据到达时非常有用,例如在非阻塞I/O或事件驱动的编程模型中。
  4. MSG_OOB
    • 作用:接收带外数据(Out-of-Band Data)。带外数据通常用于发送紧急数据,这些数据会被接收方优先处理。然而,并非所有协议都支持带外数据。
    • 使用场景:在需要处理紧急数据或优先级较高的消息时非常有用,但应确保所使用的协议支持带外数据。
  5. MSG_TRUNC
    • 作用:如果接收到的数据长度超过了缓冲区长度,则只返回缓冲区长度的数据,并截断多余的数据。然而,需要注意的是,并非所有系统都支持这个标志。
    • 使用场景:在需要限制接收数据的大小或处理不完整数据时可能有用。
  6. MSG_CTRUNC
    • 作用:类似于MSG_TRUNC,但用于控制信息的截断。如果接收到的控制信息长度超过了缓冲区长度,则只返回缓冲区长度的控制信息。
    • 使用场景:在处理带有控制信息的套接字时可能有用。
  7. MSG_ERRQUEUE
    • 作用:接收错误信息。如果接收到的数据包出现错误,则会将错误信息放入错误队列中,可以通过此标志来接收这些错误信息。
    • 使用场景:在需要处理套接字错误或诊断网络问题时非常有用。

fd是文件描述符,也就是accept函数的返回值,buf存放数据,count是接收数据的最大大小,防止越界。

6)连接其他主机

上面我们只说了如何被动连接其他主机,但我们该如何主动连接其他主机呢?使用connect函数我们主动连接其他主机,是需要设置协议和IP,端口号信息的。注意connect连接成功之后这个scokfd就被占用了,用来后续的通信,需要继续使用socket函数创建与多台主机建立连接。这是与accept函数不同的地方,accept函数是创建了新的文件描述符,sockfd还可以继续监听。

成功返回0,失败返回-1,其他这些前面都讲过,老生常谈了,无需多言。

7)TCP简单的发送数据和接收数据服务器

服务端

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include<unistd.h>#include <arpa/inet.h>#include <netinet/in.h>#include<iostream>using namespace std;#define PORT 8080#define IP "127.0.0.1"int main(){//SOCK_STREAM代表字节流,适用于TCPint fd=socket(AF_INET,SOCK_STREAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;return -1;}//IPV4结构体struct sockaddr_in _addr; //设置为IPV4协议_addr.sin_family=AF_INET;//端口号网络字节序_addr.sin_port=htons(PORT);//IP地址网络字节序,inet_addr函数将C风格字符串的IP地址形式转化成uint32_t的网络字节序类型_addr.sin_addr.s_addr=inet_addr(IP);//成功返回0,失败返回-1设置错误码int result=bind(fd,(struct sockaddr*)&_addr,(socklen_t)sizeof(_addr));if(result!=0){cout<<"绑定端口号失败"<<endl;return -1;}//允许同时最大与三个主机建立连接result=listen(fd,3);if(result!=0){cout<<"套接字启动监听失败"<<endl;return -1;}while(1){//这里不对对方主机信息进行处理,设置为空int fd_net=accept(fd,NULL,NULL);if(fd_net==-1){cout<<"TCP连接失败"<<endl;return -1;}char msg[13]="hello world!";//进行处理,发送或者接收数据result=send(fd_net,(void*)msg,13,0);close(fd);}return 0;}

客户端

       #include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include<unistd.h>#include <arpa/inet.h>#include <netinet/in.h>#include<iostream>using namespace std;#define PORT 8080#define IP "127.0.0.1"int main(){//SOCK_STREAM代表字节流,适用于TCPint fd=socket(AF_INET,SOCK_STREAM,0);if(fd<0){cout<<"创建套接字失败"<<endl;return -1;}//IPV4结构体struct sockaddr_in _addr; //设置为IPV4协议_addr.sin_family=AF_INET;//端口号网络字节序_addr.sin_port=htons(PORT);_addr.sin_addr.s_addr=inet_addr(IP);int result=connect(fd,(struct sockaddr*)&_addr,(socklen_t)sizeof(_addr));if(result==-1){cout<<"连接主机失败"<<endl;return -1;}char msg[20];result=recv(fd,msg,20,0);for(int i=0;i<result;i++){cout<<msg[i];}close(fd);return 0;}

创造不易,我为人人,人人为我,如果大家有所收获的话可以点赞加关注,下一篇文章将会着重讲TCP与UDP的特性。

相关文章:

Socket编程(TCP/UDP详解)

前言&#xff1a;之前因为做项目和找实习没得空&#xff0c;计算机网络模块并没有写成博客&#xff0c;最近得闲了&#xff0c;把计算机网络模块博客补上。 目录 一&#xff0c;UDP编程 1&#xff09;创建套接字 2&#xff09;绑定端口号 3&#xff09;发送与接收数据 4&…...

qt QConicalGradient详解

1、概述 QConicalGradient是Qt框架中QGradient的一个子类&#xff0c;它用于创建锥形渐变效果。锥形渐变是从一个中心点出发&#xff0c;沿着360度的圆周扩散的颜色渐变。这种渐变通常用于模拟光线旋转、创建彩虹效果或实现其他复杂的颜色过渡。QConicalGradient允许你定义渐变…...

存储过程与自然语言处理逻辑的不同与结合

在现代软件开发中&#xff0c;存储过程与自然语言处理&#xff08;NLP&#xff09;逻辑都发挥着重要作用。存储过程是一种在数据库内部运行的预编译程序&#xff0c;通常用于处理与数据相关的任务&#xff0c;例如插入、更新、删除数据以及复杂的查询操作。而自然语言处理&…...

了解Linux —— 理解其中的权限

前言 在了解Linux权限之前&#xff0c;先来探讨我们使用的shell 命令它到底是什么&#xff1f; Linux 是一个操作系统&#xff0c;我们称其为内核(kernel) &#xff0c;正常情况下&#xff0c;我们一般用户操作并不是去直接使用内核&#xff0c;而是通过kernel 的外壳程序&…...

知识图谱嵌入与因果推理的结合

知识图谱通过节点&#xff08;实体&#xff09;和边&#xff08;关系&#xff09;来表示现实世界中的信息&#xff0c;但如何将这些信息转化为可进行推理和决策的形式&#xff0c;仍然是一个挑战。 另一方面&#xff0c;因果推理&#xff08;Causal Inference&#xff09;作为…...

STM32 PWM波形详细图解

目录 前言 一 PWM介绍 1.1 PWM简介 1.2 STM32F103 PWM介绍 1.3 时钟周期与占空比 二.引脚映像关系 2.1引脚映像与寄存器 2.2 复用功能映像 三. PWM 配置步骤 3.1相关原理图 3.2配置流程 3.2.1 步骤一二&#xff1a; 3.2.2 步骤三&#xff1a; 3.2.3 步骤四五六七&#xff1a; …...

Python Web 开发 FastAPI 入门:从基础架构到框架比较

Python Web 开发 FastAPI 入门&#xff1a;从基础架构到框架比较 目录 &#x1f5a5;️ Web 服务器概述&#xff08;如 Nginx、Apache&#xff09;&#x1f517; 前后端分离架构详解&#x1f504; HTTP 路由和请求处理机制&#x1f9f0; Web 框架概述&#xff1a;Django、Fla…...

基于STM32的智能仓库管理系统设计

目录 引言环境准备 硬件准备软件准备智能仓库管理系统基础 控制系统架构功能描述代码实现&#xff1a;实现智能仓库管理系统 4.1 RFID标签读取模块4.2 库存管理模块4.3 数据显示与监控模块4.4 无线通信模块应用场景&#xff1a;智能仓库管理系统优化问题解决方案与优化收尾与总…...

排序算法--堆排序【图文详解】

“留在码头的船才最安全” “但亲爱的&#xff0c;那不是造船的目的。 堆--插入heapInsert 原来有一个大根堆&#xff0c;如图&#xff1a; 现在要新插入一个数字50&#xff0c;进行插入 流程&#xff1a;和父亲相比&#xff0c;如果比父亲大&#xff0c;和父亲交换&#xff…...

FCBP 认证考试要点摘要

理论知识 数据处理与分析&#xff1a;包括数据的收集、清洗、转换、存储等基础操作&#xff0c;以及数据分析方法&#xff0c;如描述性统计分析、相关性分析、数据挖掘算法等的理解和应用 。数据可视化&#xff1a;涉及图表类型的选择与应用&#xff0c;如柱状图、折线图、饼图…...

鸿蒙生态崛起的机遇有什么

鸿蒙生态系统的崛起为各个领域带来了多个机遇&#xff0c;主要体现在以下几个方面&#xff1a; 智能设备的互联互通&#xff1a;鸿蒙系统旨在实现不同设备之间的无缝连接&#xff0c;为物联网&#xff08;IoT&#xff09;设备的发展提供了良好的基础。这将推动智能家居、智慧城…...

基础(函数、枚举)错题汇总

枚举默认从0开始&#xff0c;指定后会按顺序赋值 而这个枚举变量X&#xff0c;如果在全局&#xff08;函数外部&#xff09;定义&#xff0c;那默认为0&#xff0c;如果在函数内部&#xff08;局部变量&#xff09;&#xff0c;那就是随机值&#xff0c;必须初始化。 枚举变量…...

【Spark源码分析】规则框架- `analysis`分析阶段使用的规则

analysis分析阶段使用的规则 规则批策略规则说明SubstitutionfixedPointOptimizeUpdateFields该规则优化了 UpdateFields 表达式链&#xff0c;因此看起来更像优化规则。但是&#xff0c;在处理深嵌套模式时&#xff0c;UpdateFields 表达式树可能会非常复杂&#xff0c;导致分…...

mysql--二进制安装编译安装yum安装

二进制安装 创建用户和组 [rootlocalhost ~]# groupadd -r -g 306 mysql [rootlocalhost ~]# useradd -r -g 306 -u 306 -d /data/mysql mysql 创建文件夹并添加所属文件用户和组 [rootlocalhost ~]# mkdir -p /data/mysql [rootlocalhost ~]# chown mysql:mysql /data/mysql …...

《Django 5 By Example》阅读笔记:p339-p358

《Django 5 By Example》学习第12天&#xff0c;p339-p358总结&#xff0c;总计20页。 一、技术总结 1.项目(购物网站) django-admin startproject myshop 虽然这里只是示例&#xff0c;但我觉得这种命名为 myxxx 的习惯非常不好&#xff0c;因为在实际应用中&#xff0c;是…...

鸿蒙修饰符

文章目录 一、引言1.1 什么是修饰符1.2 修饰符在鸿蒙开发中的重要性1.3 修饰符的作用机制 二、UI装饰类修饰符2.1 Styles修饰符2.1.1 基本概念和使用场景2.1.2 使用示例2.1.3 最佳实践 2.2 Extend修饰符2.2.1 基本概念2.2.2 使用示例2.2.3 Extend vs Styles 对比2.2.4 使用建议…...

springboot359智慧草莓基地管理系统(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;智慧草莓基地管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本智慧草莓基地管理系统就…...

单片机位数对性能会产生什么影响?!

单片机的位数是指其处理器核心的位宽&#xff0c;通常以比特&#xff08;bit&#xff09;为单位。常见的位数有8位、16位、32位和64位等。 单片机位数越高&#xff0c;处理器能够处理的数据量越大&#xff0c;性能也相应提高。 以下是对单片机位数对性能影响的详细分析&#…...

stm32内部高速晶振打开作为主时钟

首先建议你别这么干&#xff0c;因为内部晶振特别容易受温度等外界影响&#xff0c;很容易卡死或堵死程序 我是因为没画外部晶振电路&#xff0c;所以只能开内部晶振来作为时钟 适用于stm32f103系列 把下面的代码换掉源文件里的时钟源配置 /* 开启HSI 即内部晶振时钟 */RCC…...

【分页查询】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...