Socket网络编程(三)——TCP快速入门

概述

  1. TCP是什么
    英语:Transmission Control Protocol,缩写为 TCP
    TCP是传输控制协议;是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义
    与UDP一样完成第四层传输层所指定的功能与职责

  2. TCP的机制
    三次握手、四次挥手
    具有校验机制、可靠、数据传输稳定

  3. TCP能做什么
    聊天消息传输、推送
    单人语音、视频聊天等
    几乎UDP能做的都能做,但需要考虑复杂性、性能问题
    限制:无法进行广播,多播等操作

TCP连接可靠性

1. 三次握手过程

20240228-020352-Ph.png
三次握手的过程包括:

第一次握手:客户端发送SYN包,携带自己的序列号。
第二次握手:服务器端回复SYN+ACK包,确认收到客户端的SYN包,并携带自己的序列号。
第三次握手:客户端回复ACK包,确认收到的SYN+ACK包,完成握手过程。

这个过程确保了后续数据的可靠传输和完整性,保障了网络通信的稳定性和可靠性。

2. 四次挥手过程

20240228-020858-ym.png
四次挥手是TCP协议中用于终止连接的过程,这个过程涉及到客户端和服务端之间发送四个数据包。由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。在四次挥手中,首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。1234

以下是四次挥手的详细步骤:

第一次挥手:客户端发送一个FIN报文,用来关闭客户端到服务器的数据传送。此时客户端进入FIN_WAIT_1状态.
第二次挥手:服务器收到FIN报文后,发送一个ACK报文作为响应,确认序号为收到序号加1。此时服务器进入CLOSE_WAIT状态。
第三次挥手:服务器完成数据发送任务后,发送一个FIN报文,用来关闭服务器到客户端的数据传送。此时服务器进入LAST_ACK状态。
第四次挥手:客户端收到FIN报文后,发送一个ACK报文作为响应,确认序号为收到序号加1。此时客户端进入TIME_WAIT状态。客户端在等待一段时间(通常为2MSL,即最大报文段寿命)后,如果没有收到服务器的任何响应,则进入CLOSE状态。

这个过程确保了双方都能正确关闭连接,避免了数据丢失。

3. 为什么挥手需要四次?

由于 TCP 的半关闭(half-close)特性,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。

任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
通俗的来说,两次握手就可以释放一端到另一端的 TCP 连接,完全释放连接一共需要四次握手。

可以用下面这个例子理解:

举个例子:A 和 B 打电话,通话即将结束后,A 说 “我没啥要说的了”,B 回答 “我知道了”,于是 A 向 B 的连接释放了。但是 B 可能还会有要说的话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,于是 B 向 A 的连接释放了,这样整个通话就结束了。

传输可靠性

  1. 排序、顺序发送、顺序组装
  2. 丢弃、超时
  3. 重发机制-定时器

数据传输示意图
20240228-022539-2k.png

TCP核心API

socket():创建—个Socket
bind():绑定一个Socket到一个本地地址和端口上
connect():连接到远程套接字
accept():接受一个新的连接
write():把数据写入到Socket输出流
read():从Socket输入流读取数据

客户端Socket创建流程:
20240228-013916-lO.png

服务端ServerSocket创建流程:
20240228-014016-IO.png

Socket和进程的关系:
20240228-014241-Xq.png

TCP传输初始化配置&建立连接

  1. 初始化服务器TCP链接监听
  2. 初始化客户端发起链接操作
  3. 服务器Socket链接处理

客户端创建Socket建立连接

  1. 创建Socket基本方法和构造函数
private static Socket createSocket() throws IOException {/*// 无代理模式,等效于空构造函数Socket socket = new Socket(Proxy.NO_PROXY);// 新建一份具有HTTP代理的套接字,传输数据将通过www.baidu.com:8080端口转发Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(Inet4Address.getByName("www.baidu.com"), 8800));socket = new Socket(proxy);// 新建一个套接字,并且直接链接到本地20000的服务器上socket = new Socket("localhost", PORT);// 新建一个套接字,并且直接链接到本地20000的服务器上socket = new Socket(Inet4Address.getLocalHost(), PORT);// 新建一个套接字,并且直接链接到本地20000的服务器上,并且绑定到本地20001端口上socket = new Socket("localhost", PORT, Inet4Address.getLocalHost(), LOCAL_PORT);socket = new Socket(Inet4Address.getLocalHost(), PORT, Inet4Address.getLocalHost(), LOCAL_PORT);*/Socket socket = new Socket();// 绑定到本地20001端口socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), LOCAL_PORT));return socket;}
  1. 初始化Socket的基本配置
private static void initSocket(Socket socket) throws SocketException {// 设置读取超时时间为2秒socket.setSoTimeout(2000);// 是否复用未完全关闭的Socket地址,对于指定bind操作后的套接字有效socket.setReuseAddress(true);// 是否开启Nagle算法socket.setTcpNoDelay(true);// 是否需要在长时无数据响应时发送确认数据(类似心跳包),时间大约为2小时socket.setKeepAlive(true);// 对于close关闭操作行为进行怎样的处理;默认为false,0// false、0:默认情况,关闭时立即返回,底层系统接管输出流,将缓冲区内的数据发送完成// true、0:关闭时立即返回,缓冲区数据抛弃,直接发送RST结束命令到对方,并无需经过2MSL等待// true、200:关闭时最长阻塞200毫秒,随后按第二情况处理socket.setSoLinger(true, 20);// 是否让紧急数据内敛,默认false;紧急数据通过 socket.sendUrgentData(1);发送socket.setOOBInline(true);// 设置接收发送缓冲器大小socket.setReceiveBufferSize(64 * 1024 * 1024);socket.setSendBufferSize(64 * 1024 * 1024);// 设置性能参数:短链接,延迟,带宽的相对重要性socket.setPerformancePreferences(1, 1, 0);}
  1. 客户端手动连接
public static void main(String[] args) throws IOException {Socket socket = createSocket();initSocket(socket);// 链接到本地20000端口,超时时间3秒,超过则抛出超时异常socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 3000);System.out.println("已发起服务器连接,并进入后续流程~");System.out.println("客户端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());System.out.println("服务器信息:" + socket.getInetAddress() + " P:" + socket.getPort());try {// 发送接收数据todo(socket);} catch (Exception e) {System.out.println("异常关闭");}// 释放资源socket.close();System.out.println("客户端已退出~");}

服务端创建ServerSocket监听连接

  1. 创建ServerSocket方法
private static ServerSocket createServerSocket() throws IOException {// 创建基础的ServerSocketServerSocket serverSocket = new ServerSocket();// 绑定到本地端口20000上,并且设置当前可允许等待链接的队列为50个//serverSocket = new ServerSocket(PORT);// 等效于上面的方案,队列设置为50个//serverSocket = new ServerSocket(PORT, 50);// 与上面等同// serverSocket = new ServerSocket(PORT, 50, Inet4Address.getLocalHost());return serverSocket;}
  1. 初始化ServerSocket配置
private static void initServerSocket(ServerSocket serverSocket) throws IOException {// 是否复用未完全关闭的地址端口serverSocket.setReuseAddress(true);// 等效Socket#setReceiveBufferSizeserverSocket.setReceiveBufferSize(64 * 1024 * 1024);// 设置serverSocket#accept超时时间// serverSocket.setSoTimeout(2000);// 设置性能参数:短链接,延迟,带宽的相对重要性serverSocket.setPerformancePreferences(1, 1, 1);}
  1. 监听服务端固定端口,并且接受客户端建立连接
private static final int PORT = 20000;public static void main(String[] args) throws IOException {ServerSocket server = createServerSocket();initServerSocket(server);// 绑定到本地端口上server.bind(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 50);System.out.println("服务器准备就绪~");System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());// 等待客户端连接for (; ; ) {// 得到客户端Socket client = server.accept();// 客户端构建异步线程ClientHandler clientHandler = new ClientHandler(client);// 启动线程clientHandler.start();}}

ServerSocket 和 Socket的关系

serverSocket 和 Socket 都是 Java 中用于网络通信的类,但它们有不同的作用。

Socket 是用于建立连接的类,它可以让客户端和服务器之间相互通信。

ServerSocket 是用于监听连接请求的类,它在服务器端等待客户端的连接请求,并在连接成功后与客户端建立对应的 Socket 连接。

具体工作原理可以简单描述为:

当客户端与服务器建立连接时,客户端通过创建 Socket 对象实现,服务器端则通过创建 ServerSocket 对象实现。
客户端向服务器发送连接请求,请求中包含了要连接的服务器地址和端口号。
ServerSocket 接收到连接请求后,会生成一个 Socket 对象与客户端连接,并返回此连接对应的 Socket 对象。
客户端和服务器之间即可通过这个连接进行通信。

总之,ServerSocket 是用于监听连接请求的类,而 Socket 则是用于实现连接并进行通信的类。

Socket基本数据类型传输

基础类型数据传输

  • byte、 char、 short
  • boolean、 int、 long
  • float、 double、 string

客户端数据传输

  1. 客户端使用Socket输出流将客户端的数据传输出去
  2. 建立连接之后将各种数据类型的数据转换成byte字节数组,然后通过ByteBuffer工具统一放入字节流
    (这里使用到了一个ByteBuffer工具,这是一个字节缓冲区,后面会详细介绍)
  3. 最后通过Socket的输出流把数据发送给服务端

代码如下:

private static void todo(Socket client) throws IOException {// 得到Socket输出流OutputStream outputStream = client.getOutputStream();// 得到Socket输入流InputStream inputStream = client.getInputStream();byte[] buffer = new byte[256];ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);// bytebyteBuffer.put((byte) 126);// charchar c = 'a';byteBuffer.putChar(c);// intint i = 2323123;byteBuffer.putInt(i);// boolboolean b = true;byteBuffer.put(b ? (byte) 1 : (byte) 0);// Longlong l = 298789739;byteBuffer.putLong(l);// floatfloat f = 12.345f;byteBuffer.putFloat(f);// doubledouble d = 13.31241248782973;byteBuffer.putDouble(d);// StringString str = "Hello你好!";byteBuffer.put(str.getBytes());// 发送到服务器outputStream.write(buffer, 0, byteBuffer.position() + 1);// 接收服务器返回int read = inputStream.read(buffer);System.out.println("收到数量:" + read);// 资源释放outputStream.close();inputStream.close();}

服务端数据接收

  1. 获取监听到连接的客户端Socket套接字流
  2. 将流读取出来,转换成ByteBuffer
  3. 最后根据不同的数据类型将ByteBuffer中的数据读取并且打印出来
/*** 客户端消息处理*/private static class ClientHandler extends Thread {private Socket socket;ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {super.run();System.out.println("新客户端连接:" + socket.getInetAddress() +" P:" + socket.getPort());try {// 得到套接字流OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();byte[] buffer = new byte[256];int readCount = inputStream.read(buffer);ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);// bytebyte be = byteBuffer.get();// charchar c = byteBuffer.getChar();// intint i = byteBuffer.getInt();// boolboolean b = byteBuffer.get() == 1;// Longlong l = byteBuffer.getLong();// floatfloat f = byteBuffer.getFloat();// doubledouble d = byteBuffer.getDouble();// Stringint pos = byteBuffer.position();String str = new String(buffer, pos, readCount - pos - 1);System.out.println("收到数量:" + readCount + " 数据:"+ be + "\n"+ c + "\n"+ i + "\n"+ b + "\n"+ l + "\n"+ f + "\n"+ d + "\n"+ str + "\n");outputStream.write(buffer, 0, readCount);outputStream.close();inputStream.close();} catch (Exception e) {System.out.println("连接异常断开");} finally {// 连接关闭try {socket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("客户端已退出:" + socket.getInetAddress() +" P:" + socket.getPort());}}

TCP连接客户端、服务端完整代码

服务端代码:

package cn.kt.SocketDemoL4;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;public class Server {private static final int PORT = 20000;public static void main(String[] args) throws IOException {ServerSocket server = createServerSocket();initServerSocket(server);// 绑定到本地端口上server.bind(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 50);System.out.println("服务器准备就绪~");System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());// 等待客户端连接for (; ; ) {// 得到客户端Socket client = server.accept();// 客户端构建异步线程ClientHandler clientHandler = new ClientHandler(client);// 启动线程clientHandler.start();}}private static ServerSocket createServerSocket() throws IOException {// 创建基础的ServerSocketServerSocket serverSocket = new ServerSocket();// 绑定到本地端口20000上,并且设置当前可允许等待链接的队列为50个//serverSocket = new ServerSocket(PORT);// 等效于上面的方案,队列设置为50个//serverSocket = new ServerSocket(PORT, 50);// 与上面等同// serverSocket = new ServerSocket(PORT, 50, Inet4Address.getLocalHost());return serverSocket;}private static void initServerSocket(ServerSocket serverSocket) throws IOException {// 是否复用未完全关闭的地址端口serverSocket.setReuseAddress(true);// 等效Socket#setReceiveBufferSizeserverSocket.setReceiveBufferSize(64 * 1024 * 1024);// 设置serverSocket#accept超时时间// serverSocket.setSoTimeout(2000);// 设置性能参数:短链接,延迟,带宽的相对重要性serverSocket.setPerformancePreferences(1, 1, 1);}/*** 客户端消息处理*/private static class ClientHandler extends Thread {private Socket socket;ClientHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {super.run();System.out.println("新客户端连接:" + socket.getInetAddress() +" P:" + socket.getPort());try {// 得到套接字流OutputStream outputStream = socket.getOutputStream();InputStream inputStream = socket.getInputStream();byte[] buffer = new byte[256];int readCount = inputStream.read(buffer);ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, readCount);// bytebyte be = byteBuffer.get();// charchar c = byteBuffer.getChar();// intint i = byteBuffer.getInt();// boolboolean b = byteBuffer.get() == 1;// Longlong l = byteBuffer.getLong();// floatfloat f = byteBuffer.getFloat();// doubledouble d = byteBuffer.getDouble();// Stringint pos = byteBuffer.position();String str = new String(buffer, pos, readCount - pos - 1);System.out.println("收到数量:" + readCount + " 数据:"+ be + "\n"+ c + "\n"+ i + "\n"+ b + "\n"+ l + "\n"+ f + "\n"+ d + "\n"+ str + "\n");outputStream.write(buffer, 0, readCount);outputStream.close();inputStream.close();} catch (Exception e) {System.out.println("连接异常断开");} finally {// 连接关闭try {socket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("客户端已退出:" + socket.getInetAddress() +" P:" + socket.getPort());}}
}

客户端代码

package cn.kt.SocketDemoL4;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;public class Client {private static final int PORT = 20000;private static final int LOCAL_PORT = 20001;public static void main(String[] args) throws IOException {Socket socket = createSocket();initSocket(socket);// 链接到本地20000端口,超时时间3秒,超过则抛出超时异常socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), PORT), 3000);System.out.println("已发起服务器连接,并进入后续流程~");System.out.println("客户端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());System.out.println("服务器信息:" + socket.getInetAddress() + " P:" + socket.getPort());try {// 发送接收数据todo(socket);} catch (Exception e) {System.out.println("异常关闭");}// 释放资源socket.close();System.out.println("客户端已退出~");}private static Socket createSocket() throws IOException {/*// 无代理模式,等效于空构造函数Socket socket = new Socket(Proxy.NO_PROXY);// 新建一份具有HTTP代理的套接字,传输数据将通过www.baidu.com:8080端口转发Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(Inet4Address.getByName("www.baidu.com"), 8800));socket = new Socket(proxy);// 新建一个套接字,并且直接链接到本地20000的服务器上socket = new Socket("localhost", PORT);// 新建一个套接字,并且直接链接到本地20000的服务器上socket = new Socket(Inet4Address.getLocalHost(), PORT);// 新建一个套接字,并且直接链接到本地20000的服务器上,并且绑定到本地20001端口上socket = new Socket("localhost", PORT, Inet4Address.getLocalHost(), LOCAL_PORT);socket = new Socket(Inet4Address.getLocalHost(), PORT, Inet4Address.getLocalHost(), LOCAL_PORT);*/Socket socket = new Socket();// 绑定到本地20001端口socket.bind(new InetSocketAddress(Inet4Address.getLocalHost(), LOCAL_PORT));return socket;}private static void initSocket(Socket socket) throws SocketException {// 设置读取超时时间为2秒socket.setSoTimeout(2000);// 是否复用未完全关闭的Socket地址,对于指定bind操作后的套接字有效socket.setReuseAddress(true);// 是否开启Nagle算法socket.setTcpNoDelay(true);// 是否需要在长时无数据响应时发送确认数据(类似心跳包),时间大约为2小时socket.setKeepAlive(true);// 对于close关闭操作行为进行怎样的处理;默认为false,0// false、0:默认情况,关闭时立即返回,底层系统接管输出流,将缓冲区内的数据发送完成// true、0:关闭时立即返回,缓冲区数据抛弃,直接发送RST结束命令到对方,并无需经过2MSL等待// true、200:关闭时最长阻塞200毫秒,随后按第二情况处理socket.setSoLinger(true, 20);// 是否让紧急数据内敛,默认false;紧急数据通过 socket.sendUrgentData(1);发送socket.setOOBInline(true);// 设置接收发送缓冲器大小socket.setReceiveBufferSize(64 * 1024 * 1024);socket.setSendBufferSize(64 * 1024 * 1024);// 设置性能参数:短链接,延迟,带宽的相对重要性socket.setPerformancePreferences(1, 1, 0);}private static void todo(Socket client) throws IOException {// 得到Socket输出流OutputStream outputStream = client.getOutputStream();// 得到Socket输入流InputStream inputStream = client.getInputStream();byte[] buffer = new byte[256];ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);// bytebyteBuffer.put((byte) 126);// charchar c = 'a';byteBuffer.putChar(c);// intint i = 2323123;byteBuffer.putInt(i);// boolboolean b = true;byteBuffer.put(b ? (byte) 1 : (byte) 0);// Longlong l = 298789739;byteBuffer.putLong(l);// floatfloat f = 12.345f;byteBuffer.putFloat(f);// doubledouble d = 13.31241248782973;byteBuffer.putDouble(d);// StringString str = "Hello你好!";byteBuffer.put(str.getBytes());// 发送到服务器outputStream.write(buffer, 0, byteBuffer.position() + 1);// 接收服务器返回int read = inputStream.read(buffer);System.out.println("收到数量:" + read);// 资源释放outputStream.close();inputStream.close();}
}

执行结果

  1. 运行服务端
    20240228-151715-ZN.png

  2. 运行客户端
    20240228-151741-r9.png

  3. 服务端接收到消息并输出

20240228-151758-6Y.png

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

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

相关文章

AI芯片行业深度:发展现状、竞争格局、市场空间及相关公司深度梳理

从广义上讲只要能够运行人工智能算法的芯片都叫作AI芯片,但通常意义上的AI芯片指的是针对人工智能算法做了特殊加速设计的芯片。AI芯片也被称为AI加速器或计算卡,即专门用于处理人工智能应用中的大量计算任务的模块(其他非计算任务仍由CPU负责…

ACwing :1221 四平方和 (二分)

*#include <iostream> #include <cstring> #include <algorithm>using namespace std; const int N 5e6 10; int n;struct sum{int s,c,d;bool operator < (const sum &T)const{ // 重载小于符号if(s ! T.s) return s < T.s;if(c ! T.c) …

day11_oop_fianl_satic_多态

今日内容 零、 复习昨日 一、final 二、static 三、多态 四、向上转型&向下转型 五、多态应用 零、 复习昨日 0 类封装步骤 属性私有private提供setget方法 1 继承关键词,继承的好处 extends减少代码重复为多态做准备 2 子类可以使用父类什么 非私有的属性和方法 3 方法重写…

总结:直径测量的发展历程!在线测径仪已成主要方式!

测量在生活、生产和科学探究中扮演着至关重要的角色。从古至今&#xff0c;人们对测量的探索从未停止。而外径作为一种基础的几何尺寸&#xff0c;其测量也经过了多代发展&#xff0c;直到至今被广泛应用到工业生产中的在线测径仪。本文就来介绍一下外径测量的发展历程&#xf…

【pyinstaller打包记录】Linux系统打包可执行文件后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件&#xff08;可执行程序&#xff09;的工具。它能够将 Python 代码和其相关的依赖项&#xff08;包括 Python 解释器、依赖的模块、库文件等&#xff09;打包成一个独立的可执行文件&#xff0c;方便在不同环境中运行…

【Sql Server】存储过程的创建和使用事务,常见运用场景,以及目前现状

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

浅析扩散模型与图像生成【应用篇】(五)——SDEdit

5. SDEdit: Guided Image Synthesis and Editing With Stochastic Differential Equations 该文提出一种基于SDE扩散模型的引导图像生成和编辑方法。通过使用者在原图上给出一些引导&#xff0c;比如在图像上涂鸦或者增加一个图块&#xff0c;甚至可以不给定原图&#xff0c;直…

如何从 WordPress 中的静态资源中删除查询字符串

今天有一个客户来问询&#xff0c;hostease主机创建的WordPress站点&#xff0c;在GTMetrix或Pingdom进行网站速度测试&#xff0c;看到有关查询字符串的警告。如果不想看到查询字符串的警告&#xff0c;要如何处理呢?我们测试&#xff0c;可以通过一些处理满足这个需求。我们…

三整数排序问题的解题逻辑

【题目描述】 输入3个整数&#xff0c;从小到大排序后输出。 【样例输入】 20 7 33 【样例输出】 7 20 33 【解析】 本题解法大概有3种&#xff1a; 1、穷举条件法。 此方法先判断a、b、c大小的所有可能&#xff0c;再根据各种可能性输出不同的排序。 思路是先判断a、…

C++17中的类模板参数推导

在C17之前&#xff0c;必须明确指出类模板的所有参数。自从C17起必须指明类模板参数的限制被放宽了。通过使用类模板参数推导(Class Template Argument Deduction(CTAD))&#xff0c;只要编译器能根据初始值推导出所有模板参数&#xff0c;那么就可以不指明参数。 C17中的类模板…

记录一次排查负载均衡不能创建的排查过程

故障现象&#xff0c;某云上&#xff0c;运维同事在创建负载均衡的时候&#xff0c;发现可以创建资源&#xff0c;但是创建完之后&#xff0c;不显示对应的负载均衡。 创建负载均衡时候&#xff0c;按f12发现console有如下报错 后来请后端网络同事排查日志发现&#xff0c;是后…

中科大计网学习记录笔记(十七):拥塞控制原理 | TCP 拥塞控制

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

论文学习—Model-based Adversarial Meta-Reinforcement Learning

Model-based Adversarial Meta-Reinforcement Learning Abstract1. Introduction2. Related work3 Preliminaries基于模型的强化学习&#xff08;MBRL&#xff09;:区别和联系&#xff1a; 4 Model-based Adversarial Meta-Reinforcement Learning4.1 Formulation 4.2 Computin…

LeetCode 每日一题 Day 88 - 94

2673. 使二叉树所有路径值相等的最小代价 给你一个整数 n 表示一棵 满二叉树 里面节点的数目&#xff0c;节点编号从 1 到 n 。根节点编号为 1 &#xff0c;树中每个非叶子节点 i 都有两个孩子&#xff0c;分别是左孩子 2 * i 和右孩子 2 * i 1 。 树中每个节点都有一个值&a…

好书推荐丨细说PyTorch深度学习:理论、算法、模型与编程实现

文章目录 写在前面深度学习推荐图书内容简介作者简介 推荐理由粉丝福利写在最后 写在前面 本期博主给大家推荐一本深度学习的全新正版书籍&#xff0c;感兴趣的小伙伴快来看看吧~ 深度学习 深度学习是机器学习的一个分支&#xff0c;它模仿人脑神经网络的工作原理进行复杂的…

蓝桥杯练习系统(算法训练)ALGO-986 藏匿的刺客

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 强大的kAc建立了强大的帝国&#xff0c;但人民深受其学霸及23文化的压迫&#xff0c;于是勇敢的鹏决心反抗。   kAc帝国防…

linux kernel物理内存概述(二)

目录 物理内存数据结构 设备数物理内存描述 物理内存映射 map_kernel map_mem zone数据结构 zone类型 物理内存数据结构 站在处理器角度&#xff0c;管理物理内存的最小单位是页面。使用page数据结构描述&#xff0c;通常默认大小4kB&#xff0c;采用mem_map[]数组来存…

学习java第一天(下载并配置环境+写第一个java程序)

一.安装 1.下载 直接去官网上选择与你电脑符合的版本下载 官网链接Java Archive Downloads - Java SE 8u211 and later &#xff08;拿我的为例 Windows x64版本&#xff09; ​ 2.然后安装好exe&#xff08;要让自己知道在哪&#xff09; 3.配置环境 大佬链接&#xff1…

“每一次的感应,都是对环境的温柔拥抱。”#STM32项目二 《感应开关盖垃圾桶》【上】

“每一次的感应&#xff0c;都是对环境的温柔拥抱。”#STM32项目二 《感应开关盖垃圾桶》【上】 前言预备知识1.定时器介绍11.1软件延时的优缺点1.2定时器工作原理1.3定时器的分类1.4 STM32F103C8T6定时器资源1.5通用定时器介绍 2.定时器介绍22.1定时器计数模式2.2定时器时钟源…

【VTKExamples::PolyData】第四十六期 Reflection

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例Reflection,并解析接口vtkReflectionFilter,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. Reflection …