基于socket编程实现TCP和UDP的通信流程

socket编程的常用函数,可以参考以下这篇博客

socket编程-----常用socket编程函数icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138071210

关于TCP的三次挥手、四次挥手过程和UDP的报文分析可以参考以下两篇博客

计算机网络--运输层icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138007052

TCP协议数据传输过程及报文分析icon-default.png?t=N7T8https://blog.csdn.net/ZZZCY2003/article/details/138035752


目录

一、socket

1.1、socket概述

1.2、基本概念

1.3、关键步骤

1.4、在Linux系统上执行socket过程

二、基于socket编程的TCP通信过程

2.1、基于socket编程的TCP通信流程

2.1.1、服务端(service.c)

2.1.1.1、创建socket

2.1.1.2、绑定socket到端口

2.1.1.3、开始监听连接

2.1.1.4、接受客户端连接

2.1.1.5、读取客户端发送的数据

2.1.1.6、发送响应给客户端

2.1.1.7、关闭套接字

2.1.2、客户端(client.c) 

2.1.2.1、创建socket

2.1.2.2、设置服务器地址结构并来连接服务器

2.1.2.3、发送数据给服务器

2.1.2.4、读取服务器的响应

2.1.2.5、关闭套接字

2.2、基于socket编程的TCP通信流程图

2.3、基于socket编程的TCP示例

2.3.1、服务端(service.c)

2.3.2、客户端(client.c)

三、基于socket编程的UDP通信过程

3.1、基于socket编程的UDP通信流程

3.1.1、服务端

3.1.1.1、创建socket

3.1.1.2、设置服务器地址结构

3.1.1.3、绑定socket

3.1.1.4、打印监听信息

3.1.1.5、接收数据

3.1.1.6、关闭socket

3.1.2、客户端

3.1.2.1、创建socket

3.1.2.2、设置服务器地址结构

3.1.2.3、发送数据

3.1.2.4、打印发送信息

3.1.2.5、关闭socket

3.2、基于socket编程的UDP通信流程图

3.3、基于socket编程的UDP通信示例

3.3.1、服务端(service.c)

3.3.2、客户端(client.c)


一、socket

1.1、socket概述

        Socket编程是计算机网络通信中的一种重要技术,它允许不同的计算机程序通过网络进行通信和数据交换。在Socket编程中,一个程序(通常称为客户端)通过创建Socket对象并与另一个程序(通常称为服务器)建立连接,从而进行通信。

1.2、基本概念

  1. IP地址和端口号:IP地址用于标识网络上的设备,而端口号用于标识设备上的特定服务或应用程序。Socket通过组合IP地址和端口号来唯一标识一个网络上的通信端点。

  2. 客户端与服务器:在Socket编程中,通常有一个服务器程序等待客户端的连接请求。一旦连接建立,客户端和服务器就可以互相发送和接收数据。

  3. 流式套接字(SOCK_STREAM):通常用于TCP协议,提供可靠的、面向连接的通信服务。数据按照字节流的形式发送和接收。

  4. 数据报套接字(SOCK_DGRAM):通常用于UDP协议,提供无连接的通信服务。数据以数据报的形式发送和接收,不保证数据的顺序和可靠性。

1.3、关键步骤

  1. 创建Socket:使用socket函数创建一个新的Socket对象。

  2. 绑定(Bind):对于服务器来说,需要将Socket绑定到一个特定的IP地址和端口号上,以便客户端能够连接。

  3. 监听(Listen):服务器Socket使用listen函数开始监听来自客户端的连接请求。

  4. 接受连接(Accept):服务器使用accept函数接受客户端的连接请求,并返回一个新的Socket对象用于与客户端通信。

  5. 连接(Connect):对于客户端来说,使用connect函数向服务器发起连接请求。

  6. 发送和接收数据:使用send或sendto函数发送数据,使用recv或recvfrom函数接收数据。

  7. 关闭Socket:使用close函数关闭Socket连接,释放资源。

1.4、在Linux系统上执行socket过程

假设已经写好服务端代码(service.c)和客户端代码(client.c)(注意:示例用的是C语言代码和python代码,且代码已附在文章最下面)

1、开启两个终端,并对服务端代码和客户端代码进行编译。在两个终端中分别执行以下各一条代码,作为服务端和客户端。

gcc service.c -o service
gcc client.c -o client

2、运行服务端,使服务端处于等待连接状态。等待客户端的请求连接。

./service

3、在另一个终端运行客户端,向服务端发出请求连接的请求

./client

4、最后,执行完成!

二、基于socket编程的TCP通信过程

2.1、基于socket编程的TCP通信流程

2.1.1、服务端(service.c)

2.1.1.1、创建socket
//创建socket文件描述符  
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {  
    perror("socket failed");  
    exit(EXIT_FAILURE);  
}  
2.1.1.2、绑定socket到端口
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = htons(PORT);

//绑定socket到端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
	perror("bind failed");
	exit(EXIT_FAILURE);
}
2.1.1.3、开始监听连接
//开始监听连接
if (listen(server_fd, 3) < 0) {
	perror("listen");
	exit(EXIT_FAILURE);
}
2.1.1.4、接受客户端连接
//接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
	perror("accept");
	exit(EXIT_FAILURE);
}
2.1.1.5、读取客户端发送的数据
//读取客户端发送的数据
int valread = read(new_socket, buffer, BUFFER_SIZE);
printf("%s\n", buffer);
2.1.1.6、发送响应给客户端
//发送响应给客户端
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
2.1.1.7、关闭套接字
//关闭套接字
close(server_fd);
close(new_socket);

2.1.2、客户端(client.c) 

2.1.2.1、创建socket
//创建socket文件描述符
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	perror("Socket creation error");
	exit(EXIT_FAILURE);
}
2.1.2.2、设置服务器地址结构并来连接服务器
//设置服务器地址结构
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

//连接到服务器
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
	perror("Connection failed");
	exit(EXIT_FAILURE);
}

printf("Connected to server\n");
2.1.2.3、发送数据给服务器
//发送数据给服务器
if (send(sock, hello, strlen(hello), 0) < 0) {
	perror("Send failed");
	exit(EXIT_FAILURE);
}
printf("Hello message sent\n");
2.1.2.4、读取服务器的响应
//读取服务器的响应
while ((valread = read(sock, buffer, BUFFER_SIZE - 1)) > 0) {
	buffer[valread] = '\0';
	printf("Received from server: %s\n", buffer);
}

if (valread < 0) {
	perror("Read failed");
}
2.1.2.5、关闭套接字
//关闭socket
close(sock);

2.2、基于socket编程的TCP通信流程图

2.3、基于socket编程的TCP示例

2.3.1、服务端(service.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define PORT 8080
#define BUFFER_SIZE 1024

int main() {
	int server_fd, new_socket;
	struct sockaddr_in address;
	int opt = 1;
	int addrlen = sizeof(address);
	char buffer[BUFFER_SIZE] = {0};
	const char *hello = "Hello from server";

	//创建socket文件描述符
	if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
		perror("socket failed");
		exit(EXIT_FAILURE);
	}

	//设置socket选项,允许地址重用
	if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
		perror("setsockopt");
		exit(EXIT_FAILURE);
	}

	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr("127.0.0.1");
	address.sin_port = htons(PORT);

	//绑定socket到端口
	if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
		perror("bind failed");
		exit(EXIT_FAILURE);
	}

	//开始监听连接
	if (listen(server_fd, 3) < 0) {
		perror("listen");
		exit(EXIT_FAILURE);
	}

	//接受客户端连接
	if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
		perror("accept");
		exit(EXIT_FAILURE);
	}

	//读取客户端发送的数据
	int valread = read(new_socket, buffer, BUFFER_SIZE);
	printf("%s\n", buffer);

	//发送响应给客户端
	send(new_socket, hello, strlen(hello), 0);
	printf("Hello message sent\n");
	
	//关闭套接字
	close(server_fd);
	close(new_socket);
	return 0;
}

2.3.2、客户端(client.c)

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <netdb.h>  
  
#define PORT 8080  
#define BUFFER_SIZE 1024  
  
int main() {  
    int sock = 0;  
    struct sockaddr_in serv_addr;  
    char *hello = "Hello from client";  
    char buffer[BUFFER_SIZE] = {0};  
    int valread;  
      
    //创建socket文件描述符  
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
        perror("Socket creation error");  
        exit(EXIT_FAILURE);  
    }  
      
    //设置服务器地址结构  
    memset(&serv_addr, 0, sizeof(serv_addr));  
    serv_addr.sin_family = AF_INET;  
    serv_addr.sin_port = htons(PORT);  

      
    //连接到服务器  
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {  
        perror("Connection failed");  
        exit(EXIT_FAILURE);  
    }  
      
    printf("Connected to server\n");  
      
    //发送数据给服务器  
    if (send(sock, hello, strlen(hello), 0) < 0) {  
        perror("Send failed");  
        exit(EXIT_FAILURE);  
    }  
    printf("Hello message sent\n");  
      
    //读取服务器的响应  
    while ((valread = read(sock, buffer, BUFFER_SIZE - 1)) > 0) {  
        buffer[valread] = '\0';  
        printf("Received from server: %s\n", buffer);  
    }  
      
    if (valread < 0) {  
        perror("Read failed");  
    }  
      
    //关闭socket  
    close(sock);  
    return 0;  
}

三、基于socket编程的UDP通信过程

3.1、基于socket编程的UDP通信流程

3.1.1、服务端

3.1.1.1、创建socket
//创建socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket creation failed");
	exit(EXIT_FAILURE);
}
3.1.1.2、设置服务器地址结构
//设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//具体的ip地址
server_addr.sin_port = htons(SERVER_PORT);
3.1.1.3、绑定socket
//绑定socket
if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
	perror("bind failed");
	exit(EXIT_FAILURE);
}
3.1.1.4、打印监听信息
printf("Server is listening on port %d\n", SERVER_PORT);
3.1.1.5、接收数据
//接收数据
n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&client_addr, &len);
buffer[n] = '\0';
printf("Received from client: %s\n", buffer);
3.1.1.6、关闭socket
//关闭socket
close(sockfd);

3.1.2、客户端

3.1.2.1、创建socket
//创建socket
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("socket creation failed");
	exit(EXIT_FAILURE);
}
3.1.2.2、设置服务器地址结构
//设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
	perror("Invalid address/Address not supported");
	exit(EXIT_FAILURE);
}
3.1.2.3、发送数据
//发送数据
len = sendto(sockfd, (const char *)buffer, strlen(buffer), MSG_CONFIRM,(const struct sockaddr *)&server_addr, sizeof(server_addr));
if (len < 0) {
	perror("sendto failed");
	exit(EXIT_FAILURE);
}
3.1.2.4、打印发送信息

打印一条消息到控制台,表明数据已成功发送到服务器

printf("Message sent to server: %s\n", buffer);
3.1.2.5、关闭socket
//关闭socket
close(sockfd);

3.2、基于socket编程的UDP通信流程图

3.3、基于socket编程的UDP通信示例

3.3.1、服务端(service.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

int main() {
	int sockfd;
	struct sockaddr_in server_addr, client_addr;
	socklen_t len = sizeof(client_addr);
	char buffer[BUFFER_SIZE];
	ssize_t n;

	//创建socket
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket creation failed");
		exit(EXIT_FAILURE);
	}

	//设置服务器地址结构
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//具体的ip地址
	server_addr.sin_port = htons(SERVER_PORT);

	//绑定socket
	if (bind(sockfd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
		perror("bind failed");
		exit(EXIT_FAILURE);
	}

	printf("Server is listening on port %d\n", SERVER_PORT);

	//接收数据
	n = recvfrom(sockfd, (char *)buffer, BUFFER_SIZE, MSG_WAITALL,
	             (struct sockaddr *)&client_addr, &len);
	buffer[n] = '\0';
	printf("Received from client: %s\n", buffer);

	//关闭socket
	close(sockfd);
	return 0;
}

3.3.2、客户端(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024

int main() {
	int sockfd;
	struct sockaddr_in server_addr;
	char buffer[BUFFER_SIZE] = "Hello from UDP client!";
	ssize_t len;

	//创建socket
	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket creation failed");
		exit(EXIT_FAILURE);
	}

	//设置服务器地址结构
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SERVER_PORT);
	if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
		perror("Invalid address/Address not supported");
		exit(EXIT_FAILURE);
	}

	//发送数据
	len = sendto(sockfd, (const char *)buffer, strlen(buffer), MSG_CONFIRM,
	             (const struct sockaddr *)&server_addr, sizeof(server_addr));
	if (len < 0) {
		perror("sendto failed");
		exit(EXIT_FAILURE);
	}

	printf("Message sent to server: %s\n", buffer);

	//关闭socket
	close(sockfd);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习-N维数组和访问元素

目录 N维数组访问元素 N维数组 N维数组是机器学习和神经网络的主要数据结构 访问元素 最后一个子区域中的::是跳的意思&#xff0c;这个区域说明的是从第一个元素&#xff08;即第一行第一列那个&#xff09;对行开始跳3下循环下去直到行结束、对列开始跳2下循环下去直到列…

如何解决IntelliJ IDEA 2024打开项目时频繁闪退问题

&#x1f42f; 如何解决IntelliJ IDEA 2024打开项目时频繁闪退问题 &#x1f43e; 文章目录 &#x1f42f; 如何解决IntelliJ IDEA 2024打开项目时频繁闪退问题 &#x1f43e;摘要引言正文&#x1f4d8; 识别问题&#x1f4d9; 内存配置调整步骤1: 定位vmoptions文件步骤2: 修改…

C++初阶之入门

零、什么是C C是基于C语言而产生的&#xff0c;它既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的基于对象的程序设计&#xff0c;还可以进行面向对象的程序设计。 C缺点之一&#xff0c;是相对许多语言复杂&#xff0c;而且难学难精。许多人说学…

为什么g++编译后的cpp文件名字为a,out

文章目录 为什么g编译后的cpp文件名字为a,out能修改默认名变成cpp文件名吗关于作者 为什么g编译后的cpp文件名字为a,out 在使用g编译C源代码时&#xff0c;默认情况下生成的可执行文件名为 a.out。这是由于在Unix和类Unix系统上&#xff0c;编译器的默认行为是将生成的可执行文…

可视化+多人协同技术原理和案例分享

前言 hi&#xff0c;大家好&#xff0c;我是徐小夕&#xff0c;之前和大家分享了很多可视化低代码的技术实践&#xff0c;最近也做了一款非常有意思的文档搭建引擎——Nocode/Doc&#xff1a; 也做了一些分享&#xff1a; Nocode/Doc&#xff0c;可视化 零代码打造下一代文件编…

Unity读书系列《Unity3D游戏开发》——脚本(一)

文章目录 前言一、脚本模版及其拓展1、脚本模版2、拓展脚本模版 二、脚本的生命周期三、脚本的执行顺序四、脚本序列化1、序列化数据2、serializedObject3、监听部分元素修改事件 五、定时器与间隔定时器六、工作线程&#xff08;多线程&#xff09;总结 前言 脚本在Unity的重…

Rust HTTP 客户端:易于使用、功能强大 | 开源日报 No.228

seanmonstar/reqwest Stars: 8.9k License: Apache-2.0 reqwest 是一个易于使用且功能强大的 Rust HTTP 客户端。 异步和阻塞客户端支持普通数据、JSON、urlencoded 和 multipart 数据格式可定制的重定向策略支持 HTTP 代理和系统原生 TLS 或 rustls 的 HTTPSCookie 存储功能…

RoadBEV:鸟瞰图中的道路表面重建

1. 代码地址 GitHub - ztsrxh/RoadBEV: Codes for RoadBEV: road surface reconstruction in Birds Eye View 2. 摘要 本文介绍了RoadBEV&#xff1a;鸟瞰图中的道路表面重建。道路表面条件&#xff08;特别是几何形状&#xff09;极大地影响了自动驾驶汽车的驾驶性能。基于…

就业班 第三阶段(nginx) 2401--4.22 day1 nginx1 http+nginx初识+配置+虚拟主机

一、HTTP 介绍 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。 HTTP是一个基于TCP/IP通信协议来传递数据&#xff08;HTML 文件…

ubuntu安装Qv2ray2.7.0及配置

需要下载两个文件&#xff0c;一个是zip文件&#xff0c;一个是AppImage执行程序。 执行AppImage需要先下载fuse sudo apt install libfuse2然后为AppImage赋予执行权限 sudo chmod x ./Qv2ray-v2.7.0-linux-x64.AppImage执行,执行前可以解压zip文件 ./Qv2ray-refs.tags.v1…

操作系统(Operating System)知识点复习——第十一章 I/O管理与磁盘调度

目录 0.前言 1.I/O设备 2.I/O功能的组织 3.Operating System Design Issues 4.I/O缓冲 4.1 单缓冲Single Buffer 4.2 双缓冲Double Buffer 4.3 循环缓冲 5.磁盘调度Disk Scheduling 5.1 磁盘性能参数 5.2 磁盘调度策略 ①First-in&#xff0c;first-out(FIFO) ②Pr…

鸿蒙ArkUI实战开发-如何通过上下滑动实现亮度和音量调节

场景说明 在音视频应用中通常可以通过上下滑动来调节屏幕亮度和音量大小&#xff0c;本例即为大家介绍如何实现上述UI效果。 说明&#xff1a; 由于当前亮度和音量调节功能仅对系统应用开发&#xff0c;所以本例仅讲解UI效果的实现。 效果呈现 本例效果如下&#xff1a; 当在…

决策树分析及其在项目管理中的应用

决策树分析是一种分类学习方法&#xff0c;其主要用于解决分类和回归问题。在决策树中&#xff0c;每个内部节点表示一个属性上的测试&#xff0c;每个分支代表一个属性输出&#xff0c;而每个叶节点则代表类或类分布。通过从根节点到内部节点的路径&#xff0c;可以构建一系列…

Haystack

文章目录 关于 Haystack提供 NLP项目所有阶段的功能 Building blocks组件 Components管道 Pipelines代理 Agents 基本使用 - RAG 关于 Haystack 官网&#xff1a;https://haystack.deepset.ai官方文档&#xff1a;https://docs.haystack.deepset.ai/docs/intro教程&#xff1a…

IP地址定位是怎么实现的?

IP地址定位技术的实现是一个涉及多方面技术和方法的复杂过程。IP地址作为互联网通信中的关键元素&#xff0c;每个设备在网络中都被分配一个唯一的IP地址&#xff0c;用于标识和定位网络上的设备。通过一系列技术手段&#xff0c;我们可以对这些IP地址进行分析&#xff0c;进而…

MATLAB 向量

MATLAB 向量 向量是一维数字数组。MATLAB允许创建两种类型的向量 行向量 列向量 行向量 行向量通过将元素集括在方括号中并使用空格或逗号定界元素来创建。 示例 r [7 8 9 10 11] MATLAB将执行上述语句并返回以下结果- r 7 8 9 10 11 列向量 列向量 通过将元素集括在方…

大型网站系统架构演化实例_6.使用分布式文件系统和分布式数据库系统

1.使用分布式文件系统和分布式数据库系统 任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库经过读写分离后&#xff0c;从一台服务器拆分成两台服务器&#xff0c;但是随着网站业务的发展依然不能满足需求&#xff0c;这时需要使用分布式数据库。文件系统也一…

【高校科研前沿】东北地理所在遥感领域顶刊RSE发布中国主要红树植物群落遥感分类成果

目录 01 文章简介 02 研究内容 03 文章引用 01 文章简介 论文名称&#xff1a;Mangrove species mapping in coastal China using synthesized Sentinel-2 high-separability images&#xff08;基于Sentinel-2高分离度图像的中国沿海红树群落制图&#xff09; 第一作者及…

python爬虫学习------scrapy第二部分(第三十天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

(51单片机)第十三章-STC系列51单片机功能介绍

13.1 单片机空闲与掉电模式的应用 1. 空闲模式 当单片机进入空闲模式时&#xff0c;除CPU处于休眠状态外&#xff0c;其余硬件全部处于活动状态&#xff0c;芯片中程序未涉及的数据存储器和特殊功能寄存器中的数据在空闲模式期间都将保持原值。假若定时器正在运行&#xff0c;…