17_网络编程

文章目录

  • 网络数据传输的基本原理
  • UDP
    • 发送端步骤
    • 接收端步骤
    • DatagramSocket
    • DatagramPacket
    • 举例
      • 版本1:发送端发送消息,接收端接收并打印
      • 版本2:创建一个NetworkUtils工具类优化版本1
      • 版本3:发送端接收端相互发送
      • 版本4:使用多线程
  • TCP
    • 客户端步骤
    • 服务端步骤
    • Socket
    • ServerSocket
    • 举例
      • 版本1:客户端发送消息,服务端接收并打印
      • 版本2:多个客户端发送,服务端接收(多线程处理)
      • 版本3:客户端发送对象(序列化),服务端接收
      • 版本4:客户端上传文件到服务端

网络数据传输的基本原理

在这里插入图片描述

  • ip地址
    • 唯一确定目的主机
  • port 端口号
    • 唯一确定进程
  • 协议
    • UDP协议:无连接的不可靠的协议
    • TCP协议:面向连接的可靠的协议

UDP

在这里插入图片描述

发送端步骤

  1. 创建发送端的socket对象
  2. 把要发送的数据封装成数据报包
  3. send方法发送数据报包
  4. 释放资源close

接收端步骤

  1. 创建接收端的socket对象
  2. 创建用于接收的数据报包
  3. receive方法接收数据
  4. 解析数据报包
  5. 释放资源close

DatagramSocket

类表示用来发送和接收数据报包的套接字

构造方法


DatagramSocket(int port)     //  创建数据报套接字并将其绑定到本地主机上的指定端口。

成员方法
在这里插入图片描述

DatagramPacket

此类表示数据报包

构造方法


1. 用于发送的
DatagramPacket(byte[] buf,  int offset, int length, InetAddress address, int port)      
// 构造数据报包,用来将长度为 length 偏移量为 offset  的包发送到指定主机上的指定端口号
// InetAddress address ---> ip值2. 用于接受的
DatagramPacket(byte[] buf,  int offset, int length)      
// 构造DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量。

成员方法

在这里插入图片描述

举例

版本1:发送端发送消息,接收端接收并打印


// 发送端sender
public class Sender {public static void main(String[] args) throws IOException {//   1. 创建发送端的socket对象DatagramSocket datagramSocket = new DatagramSocket(8888);//   2. 把要发送的数据封装成数据报包String s = "hello";// DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)// 构造数据报包,用来将长度为 length 偏移量为 offset  的包发送到指定主机上的指定端口号byte[] bytes = s.getBytes();InetAddress targetIP = InetAddress.getByName("127.0.0.1");int port = 9999;DatagramPacket sendPacket =new DatagramPacket(bytes, 0, bytes.length, targetIP, port);//   3. send方法发送数据报包datagramSocket.send(sendPacket);//   4. 释放资源closedatagramSocket.close();}
}———————————————————————————————————————————————————————————————————————————————————————————// 接收端receiver
public class Receiver {public static void main(String[] args) throws IOException {// 1. 创建接收端的socket对象DatagramSocket datagramSocket = new DatagramSocket(9999);// 2. 创建用于接收的数据报包// DatagramPacket(byte[] buf,  int offset, int length)// 构造DatagramPacket,用来接收长度为 length 的包,在缓冲区中指定了偏移量。byte[] bytes = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(bytes, 0, bytes.length);// 3. receive方法接收数据System.out.println("receiver before");datagramSocket.receive(receivePacket);System.out.println("receiver after");// 4. 解析数据报包byte[] data = receivePacket.getData();int length = receivePacket.getLength();int offset = receivePacket.getOffset();System.out.println(new String(data, offset, length));// 5. 释放资源closedatagramSocket.close();}
}

版本2:创建一个NetworkUtils工具类优化版本1


NetworkUtil.javapublic class NetworkUtils {// 提供一个获取发送数据报包的方法public static DatagramPacket getSendPacket(String msg, String ip, int port) throws UnknownHostException {// 把数据封装到包里byte[] bytes = msg.getBytes();InetAddress targetIP = InetAddress.getByName(ip);DatagramPacket sendPacket = new DatagramPacket(bytes, 0, bytes.length, targetIP, port);return sendPacket;}// 提供一个获取接受数据报包的方法public static DatagramPacket getReceivePacket() {// 创建接收数据报的包byte[] bytes = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(bytes, 0, bytes.length);return receivePacket;}// 提供一个解析数据报包的方法public static String parseMsg(DatagramPacket receivePacket) {byte[] bytes = receivePacket.getData();int length = receivePacket.getLength();int offset = receivePacket.getOffset();return new String(bytes,offset,length);}
}————————————————————————————————————————————————————————————————————————————————————————————// sender 发送端
public class Sender {public static void main(String[] args) throws IOException {DatagramSocket datagramSocket = new DatagramSocket(8888);String s = "hello hi";DatagramPacket sendPacket = NetworkUtils.getSendPacket(s, "127.0.0.1", 9999);datagramSocket.send(sendPacket);datagramSocket.close();}
}————————————————————————————————————————————————————————————————————————————————————————————// 接收端receiverpublic class Receiver {public static void main(String[] args) throws IOException {DatagramSocket datagramSocket = new DatagramSocket(9999);DatagramPacket receivePacket = NetworkUtils.getReceivePacket();datagramSocket.receive(receivePacket);String s = NetworkUtils.parseMsg(receivePacket);System.out.println(s);datagramSocket.close();}
}

版本3:发送端接收端相互发送


// 发送端sender
public class Sender {public static void main(String[] args) throws IOException {// 1. 创建发送端的socket对象DatagramSocket datagramSocket = new DatagramSocket(8888);// 2. 创建Scannner对象Scanner scanner = new Scanner(System.in);// while循环while (true) {// 3. 发送逻辑// 键盘接收数据String s = scanner.nextLine();// 把数据封装成数据包DatagramPacket sendPacket = NetworkUtils.getSendPacket(s, "127.0.0.1", 9999);// senddatagramSocket.send(sendPacket);// 4. 接受逻辑// 创建用于接受的数据报包DatagramPacket receivePacket = NetworkUtils.getReceivePacket();// receive方法接收datagramSocket.receive(receivePacket);// 解析String s1 = NetworkUtils.parseMsg(receivePacket);System.out.println("接收到了" + receivePacket.getSocketAddress() + "的消息" + s1);}}
}// 接收端 receiver
public class Receiver {public static void main(String[] args) throws IOException {// 创建接收端的Socket对象DatagramSocket datagramSocket = new DatagramSocket(9999);// 创建Scanner对象Scanner scanner = new Scanner(System.in);// while循环while (true) {// 接受逻辑// 创建用于接受的数据报包DatagramPacket receivePacket = NetworkUtils.getReceivePacket();// receive接受datagramSocket.receive(receivePacket);// parse解析String msg = NetworkUtils.parseMsg(receivePacket);System.out.println("接收到了" + receivePacket.getSocketAddress() + "的消息" + msg);// 发送逻辑// 键盘接收数据String s = scanner.nextLine();// 把数据封装成包DatagramPacket sendPacket = NetworkUtils.getSendPacket(s, "127.0.0.1", 8888);// senddatagramSocket.send(sendPacket);}}
}

版本4:使用多线程

在这里插入图片描述

  • 定义发送任务 SendTask 专门用来发送消息
  • 定义接收任务 receiveTask 专门用来接收消息

eg:


SendTask:
public class SenderTask implements Runnable {// DatagramSocket datagramSocketDatagramSocket datagramSocket;// String ipString ip;// int portint port;public SenderTask(DatagramSocket datagramSocket, String ip, int port) {this.datagramSocket = datagramSocket;this.ip = ip;this.port = port;}@Overridepublic void run() {// 创建Scanner对象Scanner scanner = new Scanner(System.in);// whilewhile(true){// 键盘输入消息String s = scanner.nextLine();// 把消息封装成数据报包try {DatagramPacket sendPacket = NetworkUtils.getSendPacket(s, ip, port);// senddatagramSocket.send(sendPacket);} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
}ReceiveTask:
public class ReceiveTask implements Runnable{// 成员变量DatagramSocket datagramSocket;public ReceiveTask(DatagramSocket datagramSocket) {this.datagramSocket = datagramSocket;}@Overridepublic void run() {// 只是接收数据while(true){// 创建用于接收的数据报包DatagramPacket receivePacket = NetworkUtils.getReceivePacket();// receive接收try {datagramSocket.receive(receivePacket);// 解析String s = NetworkUtils.parseMsg(receivePacket);// 打印System.out.println("s = " + s);} catch (IOException e) {e.printStackTrace();}}}
}OnePerson:
public class OnePerson {public static void main(String[] args) throws IOException {// 创建DatagramSocket对象DatagramSocket datagramSocket = new DatagramSocket(8888);// 创建发送线程 接收线程并启动new Thread(new SenderTask(datagramSocket,"127.0.0.1",9999)).start();// 创建接收线程new Thread(new ReceiveTask(datagramSocket)).start();}
}AnotherPersonpublic class AnotherPerson {public static void main(String[] args) throws IOException {// 创建DatagramSocket对象DatagramSocket datagramSocket = new DatagramSocket(9999);// 创建发送线程 接收线程并启动new Thread(new SenderTask(datagramSocket, "127.0.0.1", 8888)).start();// 创建接收线程new Thread(new ReceiveTask(datagramSocket)).start();}
}

TCP

在这里插入图片描述

客户端步骤

  1. 创建客户端Socket对象(Socket)

  2. 从socket中获取输入输出流

  3. 利用输出输出流进行读写操作

  4. 释放资源close

服务端步骤

  1. 创建服务端的socket对象(ServerSocket)

  2. 通过accept建立连接, 得到socket对象

  3. 从socket中得到输入输出流

  4. 利用输入输出流进行读写操作

  5. 释放资源

Socket

此类实现客户端套接字

构造方法


Socket(String host,  int port)       
// 创建一个流套接字并将其连接到指定主机上的指定端口号。

:这里的host指的是目的主机的指定端口

成员方法

  • 在这里插入图片描述
  • 在这里插入图片描述

ServerSocket

此类实现服务器套接字

构造方法


ServerSocket(int port)        
// 创建绑定到特定端口的服务器套接字。

成员方法

  • 在这里插入图片描述

举例

版本1:客户端发送消息,服务端接收并打印

注意事项

  • 先启动服务端,后启动客户端
  • 端口号不能重复,如果重复占用的话,换一个端口号

eg:


客户端Clientpublic class Client {public static void main(String[] args) throws IOException {// 1. 创建客户端Socket对象// Socket(String host,  int port)Socket socket = new Socket("127.0.0.1", 9999);// 2. 从socket中获取输入输出流OutputStream out = socket.getOutputStream();// 3. 利用输出输出流进行读写操作out.write("hello".getBytes());// 4. 释放资源closesocket.close();}
}服务端Serverpublic class Server {public static void main(String[] args) throws IOException {// 1. 创建服务端的socket对象(ServerSocket)// ServerSocket(int port)ServerSocket serverSocket = new ServerSocket(9999);// 2. 通过accept建立连接, 得到socket对象Socket socket = serverSocket.accept();// 3. 从socket中得到输入输出流InputStream inputStream = socket.getInputStream();// 4. 利用输入输出流进行读写操作byte[] bytes = new byte[1024];int readCount = inputStream.read(bytes);System.out.println(new String(bytes, 0, readCount));// 5. 释放资源serverSocket.close();socket.close();}
}

版本2:多个客户端发送,服务端接收(多线程处理)

eg:


客户端Clientpublic class Client {public static void main(String[] args) throws IOException {// 创建客户端的socket对象Socket socket = new Socket("127.0.0.1",9999);// 创建scanner对象Scanner scanner = new Scanner(System.in);// while循环while(true){String s = scanner.nextLine();// 从socket对象中获取输入输出流// 字节流OutputStream out = socket.getOutputStream();// 转换成字符流OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);// write
//            out.write(s.getBytes());outputStreamWriter.write(s);// flushoutputStreamWriter.flush();}}
}服务端Serverpublic class Server {public static void main(String[] args) throws IOException {// 创建服务端的socket对象ServerSocket serverSocket = new ServerSocket(9999);// 创建线程池ExecutorService pool = Executors.newFixedThreadPool(2);// while循环while (true){// 通过accept方法建立连接Socket socket = serverSocket.accept();// 向线程池中提交任务pool.submit(new ConnectTask(socket));// 使用多线程// new Thread(new ConnectTask(socket)).start();}}
}// 多线程改进
class ConnectTask implements Runnable{// 定义成员变量Socket socket;public ConnectTask(Socket socket) {this.socket = socket;}@Overridepublic void run() {// 读取数据while (true){try {InputStream in = socket.getInputStream();byte[] bytes = new byte[1024];int readCount = in.read(bytes);String s = new String(bytes, 0, readCount);System.out.println("接收到了来自" + socket.getLocalAddress()+ "端口号是:" + socket.getPort()+ "线程名是:" + Thread.currentThread().getName()+ ",内容是:" + s);} catch (IOException e) {e.printStackTrace();}}}
}

版本3:客户端发送对象(序列化),服务端接收

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream
可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象

eg:


客户端Clientpublic class Client {public static void main(String[] args) throws IOException {// 创建客户端socket对象Socket socket = new Socket("127.0.0.1", 12300);// 从socket中获取输出流OutputStream out = socket.getOutputStream();// 把输出流进行包装,包装成序列化流ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);// 创建学生对象Student student = new Student("zs", 20);// writeObjectobjectOutputStream.writeObject(student);// closeobjectOutputStream.close();socket.close();}
}服务端Serverpublic class Server {public static void main(String[] args) throws IOException, ClassNotFoundException {// 创建客户端的socket对象ServerSocket serverSocket = new ServerSocket(12300);// accept方法建立连接,得到socket对象Socket socket = serverSocket.accept();// 得到输入流InputStream in = socket.getInputStream();// 把输入流进行包装 ObjectInputStreamObjectInputStream objectInputStream = new ObjectInputStream(in);// readObjectObject o = objectInputStream.readObject();// 打印System.out.println(o);// closeobjectInputStream.close();socket.close();serverSocket.close();}
}

版本4:客户端上传文件到服务端

在这里插入图片描述

eg:


客户端Client// 客户端上传文件到服务端
public class Client {public static void main(String[] args) throws IOException {// 创建客户端的socket对象Socket socket = new Socket("127.0.0.1", 12345);// 创建自己的输入流对象FileInputStream fileInputStream = new FileInputStream("D:\\Java_test\\testPhoto.jpg");// 通过自己的输入流读取文件信息OutputStream outputStream = socket.getOutputStream();// 通过socket获取输出流对象int readCount;byte[] bytes = new byte[1024];while ((readCount = fileInputStream.read(bytes)) != -1) {// 边读边写outputStream.write(bytes, 0, readCount);}// 释放资源fileInputStream.close();outputStream.close();socket.close();}
}服务端Serverpublic class Server {public static void main(String[] args) throws IOException {// 创建服务端的socket对象ServerSocket serverSocket = new ServerSocket(12345);// 创建自己的输出流对象FileOutputStream fileOutputStream = new FileOutputStream("D:\\darkNight.jpg");// accept方法建立连接 得到socket对象Socket socket = serverSocket.accept();// 从socket中获取输入流InputStream in = socket.getInputStream();// 边读边写int readCount;byte[] bytes = new byte[1024];while ((readCount = in.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, readCount);}// 释放serverSocket.close();socket.close();fileOutputStream.close();in.close();}
}
  • 在这里插入图片描述
    Socket的半关闭

版本4plus:

eg:


客户端Clientpublic class Server {public static void main(String[] args) throws IOException {// 创建服务端的socket对象ServerSocket serverSocket = new ServerSocket(12345);// 创建自己的输出流对象FileOutputStream fileOutputStream =new FileOutputStream("D:\\darkNight.jpg");// accept方法建立连接 得到socket对象Socket socket = serverSocket.accept();// 从socket中获取输入流InputStream in = socket.getInputStream();// 边读边写int readCount;byte[] bytes = new byte[1024];while ((readCount = in.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, readCount);}OutputStream outputStream = socket.getOutputStream();outputStream.write("文件上传成功".getBytes());// 释放serverSocket.close();socket.close();fileOutputStream.close();in.close();}
}服务端Serverpublic class Server {public static void main(String[] args) throws IOException {// 创建服务端的socket对象ServerSocket serverSocket = new ServerSocket(12345);// 创建自己的输出流对象FileOutputStream fileOutputStream =new FileOutputStream("D:\\darkNight.jpg");// accept方法建立连接 得到socket对象Socket socket = serverSocket.accept();// 从socket中获取输入流InputStream in = socket.getInputStream();// 边读边写int readCount;byte[] bytes = new byte[1024];while ((readCount = in.read(bytes)) != -1) {fileOutputStream.write(bytes, 0, readCount);}OutputStream outputStream = socket.getOutputStream();outputStream.write("文件上传成功".getBytes());// 释放serverSocket.close();socket.close();fileOutputStream.close();in.close();}
}

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

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

相关文章

搭建LNMP网站平台并部署Web应用

本章主要介绍: 安装Nginx安装MySQL安装PHP在LNMP平台中部署 Web 应用 构建LNMP网站平台就像构建LAMP平台一样,构建LNMP平台也需要Linux服务器,MySQL数据库,PHP解析环境,区别主要在Nginx 与 PHP的协作配置上&#xff0…

Kotlin程序设计(三)高级用法

Kotlin程序设计高级篇 在学习了前面的内容之后,相信各位小伙伴应该对Kotlin这门语言有了一些全新的认识,我们已经了解了大部分的基本内容,从本章开始,就是对我们之前所学的基本内容的进一步提升。 泛型 在前面我们学习了最重要…

缓存代理服务器

1 缓存代理 1.1 缓存代理的概述 web代理的作用 缓存网页对象,减少重复请求 存储一些之前被访问的或且可能将要备再次访问的静态网页资源对象,使用户可以直接从缓存代理服务器获取资源,从而减少上游原始服务器的负载压力,加快整…

ubuntu20固定串口名称

查看串口的详细信息 udevadm info --name/dev/ttyUSB0结果: P: /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0 N: ttyUSB0 L: 0 S: serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UAR…

Qt 6之五:创建菜单

Qt 6之五:创建菜单 Qt是一种跨平台的C应用程序开发框架,它提供了一套丰富的工具和库,可以帮助开发者快速构建跨平台的应用程序,用于开发图形用户界面(GUI)和非GUI应用程序。 Qt 6之一:简介、安…

DHCP动态主机配置协议

文章目录 DHCP1、DHCP的优势2、DHCP的分配方式3、DHCP的租约过程4、服务器配置命令格式命令图文详解 DHCP DHCP:动态主机配置协议 1、DHCP的优势 减少管理员的工作量 避免输入错误的可能 避免IP地址冲突 当更改IP地址段时,不需要重新配置每个用户的…

Qt 三维柱状图 Q3DBar 和 三维条形图中的数据序列 QBar3DSeries

(一) 使用 Q3DBars 图形类和 QBar3DSeries 序列类可以绘制三维柱状图 窗口右侧是用 Q3DBars 和 QBar3DSeries 绘制的三维柱状图,这个图只有一个QBar3DSeries序列,数据是按行存储的,可以有多行。水平方向是行坐标轴和列坐标轴,使用…

阿里云服务器新购、续费、升级优惠政策与活动汇总

阿里云作为国内领先的云服务提供商,始终致力于为客户提供优质、高效的服务。为了更好地满足客户的需求,阿里云经常推出各种优惠政策与活动。本文将为大家详细介绍阿里云服务器的新购、续费、升级优惠政策与优惠活动,帮助大家更好地了解并利用…

雪花代码-html版

雪花代码 动画效果 代码 <!DOCTYPE html><html><head><style>body {background-color: #000000;}.snowflake {position: absolute;font-size: 10px;color: #FFFFFF;text-shadow: 1px 1px 1px #000000;user-select: none;}</style></head>…

MySQL中datetime和timestamp的区别

datetime和timestamp的区别 相同点: 存储格式相同 datetime和timestamp两者的时间格式都是YYYY-MM-DD HH:MM:SS 不同点: 存储范围不同. datetime的范围是1000-01-01到9999-12-31. 而timestamp是从1970-01-01到2038-01-19, 即后者的时间范围很小. 与时区关系. datetime是存储…

Vue.js设计与实现阅读-2

Vue.js设计与实现阅读-2 1、前言2、框架设计的核心要素2、1 提升用户体验2、2 控制代码体积2、3 Tree-Shaking2、4 特性开关2、5 错误处理 1、前言 上一篇我们了解到了 命令式和声明式的区别&#xff0c;前者关注过程&#xff0c;后者关注结果了解了虚拟dom存在的意义&#x…

Java中的多线程

进程和线程的概念 进程是应用程序的执行实例有独立的内存空间和系统资源。 线程是进程中执行运算的最小单位&#xff0c;可完成一个独立的顺序控制流程 一。一个进程可以包含多个线程&#xff0c;每个线程都独立执行特定的任务&#xff0c; 是CPU调度和分派的基本单位。 多线…

轴承滚珠故障的理论推导与计算(修订中...)

1.缘起 轴承故障故障位置在高频&#xff0c;如果不即时处理&#xff0c;恶化后&#xff0c;滚珠会有单颗故障迅速恶化到多颗&#xff0c;如果此时电机承载较大负载&#xff0c;轴承的恶化&#xff0c;会牵连到相关的动力轴。是一个不可不进行监测的项目。 2.频谱特征 轴承的…

【AWS】使用亚马逊云服务器创建EC2实例

目录 前言为什么选择 Amazon EC2 云服务器搭建 Amazon EC2 云服务器注册亚马逊账号登录控制台服务器配置免费套餐预览使用 Amazon EC2 云服务器打开服务器管理界面设置服务器区域填写实例名称选择服务器系统镜像选择实例类型创建密钥对网络设置配置存储启动实例查看实例 总结 前…

Window平台安装MongoDB

在部署前需要在官网先确定系统对应的Mongo DB版本。 本机电脑为Window10&#xff0c;所以这里以MongoDB 6.0版本。 1 在官网下载安装包 2 安装MongoDB MongoDB Compass 是一个图形界面管理工具&#xff0c;如果勾选了安装会花费长一点时间&#xff0c;可以取消掉勾选&#xff…

2024最新适用于 Windows 、Mac 的最佳屏幕录制软件

屏幕录制软件可以帮助我们录制 PC 和MacBook的实时屏幕视频。如果您想为 优酷录制视频&#xff0c;或者您正在为您的公司制作基于视频的项目&#xff0c;并且需要捕获屏幕的实时视频录制&#xff0c;那么我们在此列出了 一 款适合您的 Windows 、Mac的 2024 年最佳屏幕录制软件…

《NLP入门到精通》栏目导读

一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》&#xff0c;因此&#xff0c;读者需要一定得深度学习基础&#xff0c;才能过度到此栏目内容。 二、博客建设理念 本博客基地&am…

Transformer详解【学习笔记】

文章目录 1、Transformer绪论2、Encoders和Decoder2.1 Encoders2.1.1 输入部分2.1.2 多头注意力机制2.1.3 残差2.1.4 LayNorm&#xff08;Layer Normalization&#xff09;2.1.5 前馈神经网路 2.2 Decoder2.2.1 多头注意力机制2.2.2 交互层 1、Transformer绪论 Transformer在做…

RabbitMQ(十)队列的声明方式

目录 1.编程式声明补充&#xff1a;RabbitTemplate 和 AmqpAdmin 的区别 2.声明式声明补充&#xff1a;new Queue() 和 QueueBuilder.durable(queueName).build() 的区别 背景&#xff1a; 在学习 RabbitMQ 的使用时&#xff0c; 经常会遇到不同的队列声明方式&#xff0c;有的…

Redis管道操作

文章目录 1. 问题提出2. 解决方案3. 案例演示4. 总结 1. 问题提出 如何优化频繁命令往返造成的性能瓶颈&#xff1f; Redis是一种基于C/S一级请求响应协议的TCP服务&#xff0c;一个请求会遵循一下步骤&#xff1a; 客户端向服务端发送命令分四步&#xff08;发送命令-> …