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

Java——网络编程套接字

目录

一、网络编程基础

1.1 为什么需要网络编程?——丰富的网络资源

二、什么是网络编程?

三、网络编程中的基本概念

3.2 请求和响应

 3.3 客户端和服务端

 常见的客户端服务端模型

四、Socket套接字

五、通信模型

5.1 Java数据报套接字通信模型

5.2 Java流套接字通信模型

 Socket编程注意事项

5.3 UDP数据报套接字编程

 示例一:

示例二:


一、网络编程基础

1.1 为什么需要网络编程?——丰富的网络资源

用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源。

与本地打开视频文件类似,只是视频文件这个资源的来源是网络。

相比本地资源来说,网络提供了更为丰富的网络资源:

所谓的网络资源,其实就是在网络中可以获取的各种数据资源。

而所有的网络资源,都是通过网络编程来进行数据传输的。

二、什么是网络编程?

网络编程,指网络上的主机,通过 不同的进程 ,以编程的方式实现 网络通信(或称为网络数据传输)

当然,我们只要满足 进程 不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据, 也属于网络编程。
特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程。
但是,我们一定要明确,我们的目的是提供网络上不同主机,基于网络来传输数据资源:
  • 进程A:编程来获取网络资源
  • 进程B:编程来提供网络资源

三、网络编程中的基本概念

3.1  发送端和接收端

在一次网络数据传输时:

发送端 :数据的 发送方进程 ,称为发送端。发送端主机即网络通信中的源主机。
接收端 :数据的 接收方进程 ,称为接收端。接收端主机即网络通信中的目的主机。
收发端 :发送端和接收端两端,也简称为收发端。
注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

3.2 请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输:
  • 第一次:请求数据的发送
  • 第二次:响应数据的发送。
好比在快餐店点一份炒饭:
先要发起请求:点一份炒饭,再有快餐店提供的对应响应:提供一份炒饭

 3.3 客户端和服务端

服务端 :在常见的网络数据传输场景下,把 提供服务 的一方进程,称为服务端,可以提供对外服务。
客户端 获取服务 的一方进程,称为客户端。
对于服务来说,一般是提供:
  • 客户端获取服务资源
  • 客户端保存资源在服务端

好比在银行办事:
银行提供存款服务:用户(客户端)保存资源(现金)在银行(服务端)
银行提供取款服务:用户(客户端)获取服务端资源(银行替用户保管的现金)

 常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:

1. 客户端先发送请求到服务端
2. 服务端根据请求数据,执行相应的业务处理
3. 服务端返回响应:发送业务处理结果
4. 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

四、Socket套接字

概念
Socket 套接字,是由系统提供用于网络通信的技术,是基于 TCP/IP 协议的网络通信的基本操作单元。
基于Socket套接字的网络程序开发就是网络编程。
分类
Socket 套接字主要针对传输层协议划分为如下三类:
4.1  流套接字 :使用传输层 TCP 协议
TCP ,即 Transmission Control Protocol (传输控制协议),传输层协议。
以下为 TCP 的特点(细节后续再学习):
  • 有连接
  • 可靠传输
  • 面向字节流
  • 有接收缓冲区,也有发送缓冲区
  • 大小不限
对于字节流来说,可以简单的理解为,传输数据是基于 IO 流,流式数据的特征就是在 IO 流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。
4.2. 数据报套接字 :使用传输层 UDP 协议
UDP ,即 User Datagram Protocol (用户数据报协议),传输层协议。
以下为 UDP 的特点(细节后续再学习):
  • 无连接
  • 不可靠传输
  • 面向数据报
  • 有接收缓冲区,无发送缓冲区
  • 大小受限:一次最多传输64k
对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如 100 个字节,必须一次发送,接收也必须一次接收100 个字节,而不能分 100 次,每次接收 1 个字节。

4.3 原始套接

原始套接字用于自定义传输层协议,用于读写内核没有处理的 IP 协议数据。
我们不学习原始套接字,简单了解即可。

五、通信模型

5.1 Java数据报套接字通信模型

对于 UDP 协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报。
java 中使用 UDP 协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用
DatagramPacket 作为发送或接收的 UDP 数据报。对于一次发送及接收 UDP 数据报的流程如下:

 

以上只是一次发送端的 UDP 数据报发送,及接收端的数据报接收,并没有返回的数据。也就是只有请求,没有响应。对于一个服务端来说,重要的是提供多个客户端的请求处理及响应,流程如下:

 

5.2 Java流套接字通信模型

 Socket编程注意事项

 

1. 客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但真实的场
景,一般都是不同主机。
2. 注意目的 IP 和目的端口号,标识了一次数据传输时要发送数据的终点主机和进程
3. Socket 编程我们是使用流套接字和数据报套接字,基于传输层的 TCP UDP 协议,但应用层协议,
也需要考虑,这块我们在后续来说明如何设计应用层协议。
4. 关于端口被占用的问题
如果一个进程 A 已经绑定了一个端口,再启动一个进程 B 绑定该端口,就会报错,这种情况也叫端
口被占用。对于 java 进程来说,端口被占用的常见报错信息如下:

 

此时需要检查进程B绑定的是哪个端口,再查看该端口被哪个进程占用。以下为通过端口号查进程的方式:

  • cmd输入 netstat -ano | findstr 端口号 ,则可以显示对应进程的pid。如以下命令显
    示了 8888 进程的 pid
  • 在任务管理器中,通过pid查找进程

 解决端口被占用的问题

  • 如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B
  • 如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。

5.3 UDP数据报套接字编程

DatagramSocket API

DatagramSocket UDP Socket ,用于发送和接收 UDP 数据报。
DatagramSocket 构造方法:

 DatagramSocket 方法:

 DatagramPacket API

DatagramPacket UDP Socket 发送和接收的数据报。
DatagramPacket 构造方法:

 DatagramPacket 方法:

 构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创

建。
InetSocketAddress API
InetSocketAddress SocketAddress 的子类 )构造方法:

 

示例一:

实现一个基于TCP的回显服务

客户端:

mport java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoClient {// 定义一个用于客户端的Socket对象private Socket clientSocket;/*** 初始化客户端的Socket** @param serverIp 服务器IP地址* @param serverPort 服务器的端口号* @throws IOException*/public TCPEchoClient (String serverIp, int serverPort) throws IOException {this.clientSocket = new Socket(serverIp, serverPort);}public void start () throws IOException {System.out.println("客户端已启动...");// 获取Socket中的输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的输入while (true) {System.out.println("->");// 接收用户的输入内容Scanner requestScanner = new Scanner(System.in);String request = requestScanner.nextLine();// 发送用户的请求PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);// 强制刷新缓冲区printWriter.flush();// 接收服务器的响应Scanner responseScanner = new Scanner(inputStream);// 获取响应数据String response = responseScanner.nextLine();// 打印响应内容System.out.println("接收到服务器的响应:" + response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public static void main(String[] args) throws IOException {TCPEchoClient client = new TCPEchoClient("127.0.0.1", 9999);client.start();}
}

服务端:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ProtocolException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 基于TCP的服务器程序* @Date 2023-05-23*/
public class TCPEchoServer {// 声明一个用于服务端的Socket对象private ServerSocket server;/*** 通过指定端口号实例化服务** @param port 端口号* @throws IOException*/public TCPEchoServer(int port) throws IOException {if (port < 1025 || port > 65535) {throw new RuntimeException("端口号要在 1025 ~ 65535之间.");}// 实例化ServerSocket并指定端口号this.server = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动成功...");// 创建一个线程池ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 10, 1, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10));// 循环接收客户端的连接while (true) {Socket clientSocket = server.accept();// 每接收到一个新连接请求,就创建一个新的子线程
//            Thread thread = new Thread(() -> {
//                // 处理Socket中的数据
//                try {
//                    processConnections(clientSocket);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });
//            // 启动线程
//            thread.start();// 提交任务到线程池中poolExecutor.submit(() -> {try {processConnections(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}// 处理数据private void processConnections(Socket clientSocket) throws IOException {// 打印日志String clientInfo = MessageFormat.format("[{0}:{1}] 客户端已上线", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);// 处理数据之前要获取一下输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的请求while (true) {// 通过Scanner读取用户请求中的数据Scanner requestScanner = new Scanner(inputStream);if (!requestScanner.hasNextLine()) {// 日志clientInfo = MessageFormat.format("[{0}:{1}] 客户端已下线.", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);break;}// 获取真实的用户请求数据String request = requestScanner.nextLine();// 根据请求计算响应String response = process(request);// 把响应写回客户端PrintWriter printWriter = new PrintWriter(outputStream);// 写入输出流printWriter.println(response);// 强制刷新缓冲区printWriter.flush();// 打印日志clientInfo = MessageFormat.format("[{0}:{1}], request: {2}, response: {3}",clientSocket.getInetAddress(), clientSocket.getPort(), request, response);System.out.println(clientInfo);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}private String process(String request) {System.out.println("收到新消息:"  + request);Scanner scanner = new Scanner(System.in);String response = scanner.nextLine();return response;}public static void main(String[] args) throws IOException {TCPEchoServer server = new TCPEchoServer(9999);server.start();}
}

示例二:

实现一个基于UDP的回显服务:

客户端:

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** @Date 2023-05-20*/
public class UDPEchoClient {// 定义一个用于客户端的DatagramSocketprivate DatagramSocket client;// 定义服务器的IP地址private String serverIp;// 定义服务器的端口号private int port;private SocketAddress address;/*** 构造方法,指定服务器的Ip地址和端口号** @param serverIp 服务器IP* @param port 端口号*/public UDPEchoClient (String serverIp, int port) throws SocketException {this.client = new DatagramSocket();this.serverIp = serverIp;this.port = port;this.address = new InetSocketAddress(serverIp, port);}public void start () throws IOException {System.out.println("客户端已启动.");// 循环接收用户的输入Scanner scanner = new Scanner(System.in);while (true) {System.out.println("->");// 接收用户输入String request = scanner.next();// 1. 把请求内容包装成DatagramPacketDatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),request.getBytes().length, address);// 2. 发送数据client.send(requestPacket);// 3. 接收响应DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);// 4. 在receive方法中填充响应数据client.receive(responsePacket);// 5. 解析响应数据String response = new String(responsePacket.getData(), 0, responsePacket.getLength(), "UTF-8");// 6. 打印日志System.out.printf("request: %s, response: %s.\n", request, response);}}public static void main(String[] args) throws IOException {UDPEchoClient client = new UDPEchoClient("127.0.0.1", 9999);// 启动服务client.start();}}

服务端:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;/*** UDP 回显服务器** @Date 2023-05-20*/
public class UDPEchoServer {// 定义一个用于服务器端的DatagramSocketprivate DatagramSocket server;/*** 构造方法,完成服务器的初始化* @param port 端口号*/public UDPEchoServer (int port) throws Exception {if (port > 65535 || port < 1024) {throw new Exception("端口号必须在1024 ~ 65535之间");}// 初始化服务器端的UDP服务this.server = new DatagramSocket(port);}/*** 对外提供服务*/public void start () throws IOException {System.out.println("服务器已启动....");// 循环接收用户的请求while (true) {// 1. 创建一个用于接收请求数据的DatagramPacketDatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);// 2. 接收请求, 把真实的内容填充到requestPacketserver.receive(requestPacket);// 3. 从requestPacket获取数据String request = new String(requestPacket.getData(), 0, requestPacket.getLength(), "UTF-8");// 4. 根据请求获取响应String response = processor (request);// 5. 把响应封装到DatagramPacketDatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),response.getBytes().length, requestPacket.getSocketAddress());// 6. 发送数据server.send(responsePacket);// 7. 打印日志System.out.printf("[%s:%d] request: %s, response: %s.\n", requestPacket.getAddress().toString(),requestPacket.getPort(), request, response);}}public String processor(String request) {return request;}public static void main(String[] args) throws Exception {// 初始化服务器UDPEchoServer server = new UDPEchoServer(9999);// 启动服务server.start();}}

简单的字典功能

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** @Date 2023-05-20*/
public class UDPDictServer extends UDPEchoServer{private Map<String, String> map = new HashMap<>();/*** 构造方法,完成服务器的初始化** @param port 端口号*/public UDPDictServer(int port) throws Exception {super(port);// 初始化字典内容map.put("dog", "小狗");map.put("cat", "小猫");map.put("pig", "小猪");map.put("tiger", "大老虎");map.put("veryGood", "牛P");}@Overridepublic String processor(String request) {return map.getOrDefault(request, "查无此词");}public static void main(String[] args) throws Exception {UDPDictServer server = new UDPDictServer(9999);server.start();}
}

相关文章:

Java——网络编程套接字

目录 一、网络编程基础 1.1 为什么需要网络编程&#xff1f;——丰富的网络资源 二、什么是网络编程? 三、网络编程中的基本概念 3.2 请求和响应 3.3 客户端和服务端 常见的客户端服务端模型 四、Socket套接字 五、通信模型 5.1 Java数据报套接字通信模型 5.2 Java流…...

160套小程序源码

源码列表如下&#xff1a; AppleMusic (知乎日报) 微信小程序 d artand 今日更新求职招聘类 医药网 口碑外卖点餐 城市天气 外卖小程序 定位天气 家居在线 微信小程序-大好商城&#xff0c;wechat-weapp 微信小程序的掘金信息流 微信跳一跳小游戏源码 微票源码-demo 急救应急处…...

有效项目进度管理的 10 条规则

项目进度管理是项目中比较关键的方面之一&#xff0c;因为它将决定事情的进展方式、进展速度以及是否会取得进展。换句话说&#xff0c;它可以让你较好地控制项目&#xff0c;帮助你预测不可预测的情况&#xff0c;并使所有相关团队能够高效地协同工作。 以下是有效项目进度管…...

javaWebssh服装租赁店信息管理系统台myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh服装租赁店信息管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要 采用B/S模式开发。开发环境为TO…...

概率论:样本与总体分布,Z分数与概率

参考书目&#xff1a;《行为科学统计精要》&#xff08;第八版&#xff09;——弗雷德里克J格雷维特 数据及其样本的分布 描述一组数据分布 描述一组样本数据的分布 描述样本数据的均值和整体数据一样&#xff0c;但是样本标准差的公式除以了n-1&#xff0c;这里引入自由度的…...

【JavaSE】Java基础语法(十二):ArrayList

文章目录 1. ArrayList的构造方法和添加方法2. ArrayList类常用方法3. ArrayList存储学生对象并遍历 集合和数组的区别 : 共同点&#xff1a;都是存储数据的容器不同点&#xff1a;数组的容量是固定的&#xff0c;集合的容量是可变的 1. ArrayList的构造方法和添加方法 ArrayL…...

c++—封装:运算符重载、友元

1. 友元 &#xff08;1&#xff09;友元函数 ①是一种允许非类成员函数访问类的私有成员的一种机制&#xff1b;可以把一个函数指定为类的友元&#xff0c;也可以把整个类指定为另一个类的友元&#xff1b; ②友元函数在类作用域外定义&#xff0c;但需要在类体中进行声明&…...

【K8s】安全认证与DashBoard

文章目录 一、概述1、客户端2、认证、鉴权与准入控制 二、认证管理1、认证方式2、HTTPS证书认证 三、授权管理1、授权与RBAC2、Role 与 ClusterRole3、RoleBinding 与 ClusterRoleBinding4、案例&#xff1a;创建一个只能管理dev空间下Pods资源的账号 四、准入控制五、DashBoar…...

SpringMVC第七阶段:SpringMVC的增删改查(01)

SpringMVC的增删改查 1、准备单表的数据库 drop database if exists springmvc;create database springmvc;use springmvc; ##创建图书表 create table t_book(id int(11) primary key auto_increment, ## 主键name varchar(50) not null, ## 书名 author varchar(50) no…...

接口测试-Mock测试方法

一、关于Mock测试 1、什么是Mock测试&#xff1f; Mock 测试就是在测试过程中&#xff0c;对于某些不容易构造&#xff08;如 HttpServletRequest 必须在Servlet 容器中才能构造出来&#xff09;或者不容易获取的比较复杂的对象&#xff08;如 JDBC 中的ResultSet 对象&#…...

关于宝塔部署jar包和war包

文章目录 前言一、jar包部署二、war包部署1.maven如果打包不了使用命令打包2.安装Tomcat进行访问是否成功2.进入Tomcat目录进行配置war包 一、项目访问方法 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、jar包部署 1.其实jar包没什么讲的&…...

SpringMVC框架面试专题(初级-中级)-第十节

欢迎大家一起探讨&#xff5e;如果可以帮到大家请为我点赞关注哦&#xff5e; 截止到本节关于SpringMVC的内容已经更新完毕&#xff0c;后续会更新SpringBoot框架的面试题&#xff1b;大家在背题的时候切记不要死记硬背&#xff0c;需要理解 这是什么&#xff1f;有什么操作&a…...

PCIe TLB事务层详解过程

目录 1.What is TLP 2.PCIe 4种不同的事务 2.1.Memory事务 ​​​​​​​2.2.IO事务 2.3.Configuration事务 2.4.Message...

RK3588平台开发系列讲解(项目篇)YOLOv5部署测试

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、YOLOv5环境安装二、YOLOv5简单使用2.1、获取预训练权重文2.2、YOLOv5简单测试2.3、转换为rknn模型2.4、部署到 RK 板卡三、airockchip/yolov5简单测试3.1、转换成rknn模型并部署到板卡沉淀、分享、成长,让自己和他…...

基于变形模板的弱监督体图像分割

文章目录 Weakly Supervised Volumetric Image Segmentation with Deformed Templates摘要本文方法实验结果 Weakly Supervised Volumetric Image Segmentation with Deformed Templates 摘要 背景 有许多方法可以对网络进行弱监督训练来分割2D图像。依赖于对3D图像的2D切片的…...

python实现单例模式及其应用

单例模式是一种常见的设计模式&#xff0c;它保证一个类只能被实例化一次&#xff0c;并提供了一个全局访问点来获取这个唯一的实例。 在 Python 中&#xff0c;可以通过使用装饰器、元类或模块等方式实现单例模式。下面分别介绍这三种方法&#xff1a; 1.使用装饰器实现单例…...

SSM 如何使用 Seata 框架实现分布式事务?

SSM 如何使用 Seata 框架实现分布式事务&#xff1f; 分布式事务是现代分布式系统中必不可少的一部分&#xff0c;而 Seata 框架是一种常用的分布式事务处理方式。在 SSM 框架中&#xff0c;我们可以使用 Seata 框架来管理分布式事务。本文将介绍如何在 SSM 框架中使用 Seata …...

FreeRTOS任务相关API函数

任务创建和删除API函数 xTaskCreate() 创建任务。RAM BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务函数const char* const pcName, //任务名字const uint16_t usStackDepth,//任务堆栈大小void * const …...

VBA之正则表达式(42)-- 提取代码中变量名称

实例需求&#xff1a;待处理代码段如下所示&#xff0c;现在需要提取其中的变量名称。 Public pFactor As Integer Sub TestCode() Dim reg As New RegExp, a As Workbook Dim ms As VBScript_RegExp_55.MatchCollection Dim m As VBScript_RegExp_55.Match Dim i, j Dim x1, y…...

Unity Lightmapping Setting

如下图&#xff1a; Lightmapper: 使用什么硬件或算法渲染 Progressive CPU、Progressive GPU、Enlighten(新的算放目前用的比较少) 此数值会被用于分别乘以Direct Samples&#xff0c;Indirect Samples和Environment Samples这三个数值。这三个数值会被应用于…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...

高抗扰度汽车光耦合器的特性

晶台光电推出的125℃光耦合器系列产品&#xff08;包括KL357NU、KL3H7U和KL817U&#xff09;&#xff0c;专为高温环境下的汽车应用设计&#xff0c;具备以下核心优势和技术特点&#xff1a; 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计&#xff0c;确保在…...