网络编程与netty

news2024/11/25 20:43:45

目录

  • NIO 网络编程
    • Buffer(缓冲区)
    • Channel(通道)
    • Selector(选择器)
      • SelectionKey
    • 零拷贝
    • 原生NIO存在的问题
  • 线程模型
    • 传统阻塞 I/O 服务模型
    • Reactor 模式
      • 单 Reactor 单线程
      • 单 Reactor 多线程
      • 主从 Reactor 多线程
  • Netty 实现网络编程
    • Netty 的线程模型(架构)
      • BossGroup
      • WorkerGroup
      • BossGroup 与 WorkerGroup
      • NioEventLoop
    • 异步模型(ChannelFuture)
    • Bootstrap、ServerBootstrap
      • ChannelOption
    • Channel
    • Selector
    • ChannelHandler 及其实现类
      • 出站/入站
      • ChannelHandler 实现类中的各种方法
    • ChannelPipeline
      • 常用方法
      • ChannelHandlerContext
    • ChannelHandler 、ChannelPipeline、NioEventLoop、Channel 关系
    • Unpooled 类
    • Netty心跳检测机制
    • 编码与解码
    • TCP 粘包和拆包

NIO 网络编程

  • NIO 网络编程 有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)

Buffer(缓冲区)

  • 缓冲区(Buffer):缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,Channel 读取或写入的数据都必须经由 Buffer
    在这里插入图片描述在这里插入图片描述
  • ByteBuffer 支持类型化的put 和 get, put 放入的是什么数据类型,get就应该使用相应的数据类型来取出,否则可能有BufferUnderflowException 异常
  • 可以将一个普通Buffer 转成只读Buffer
  • NIO 还提供了 MappedByteBuffer, 可以让文件直接在内存(堆外的内存)中进行修改, 而如何同步到文件由NIO 来完成
  • NIO 还支持通过多个Buffer (即 Buffer 数组) 完成读写操作,即 Scattering 和 Gathering

Channel(通道)

  • 通道类似于流,但有些区别如下
    • 通道可以同时进行读写,而流只能读或者只能写
    • 通道可以实现异步读写数据
    • 通道可以从缓冲读数据,也可以写数据到缓冲
      在这里插入图片描述
  • Channel 常用的方法
    在这里插入图片描述

Selector(选择器)

  • Java 的 NIO,用非阻塞的 IO 方式,可以用一个线程使用 Selector 处理多个的客户端连接
  • 每个 Channel 以事件的方式可以注册到同一个Selector,Selector 能够检测多个注册的 Channel 上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的处理。这样就可以只用一个单线程去管理多个通道,也就是管理多个连接和请求
    在这里插入图片描述
  • 常用方法
//得到一个选择器对象
public static Selector  open();
//返回有事件发生的 Channel 个数,如果没有发生事件的 Channel,则阻塞指定ms,然后返回 0
public int  select(long timeout);
//返回有事件发生的 Channel 对应的 SelectionKey
public Set<SelectionKey>  selectedKeys();
//阻塞,直到有 Channel 发生事件
selector.select();
//唤醒阻塞的 selector
selector.wakeup();
//不阻塞,立马返回有事件发生的 Channel 个数 or 0
selector.selectNow();

在这里插入图片描述

SelectionKey

  • Selector 不会直接返回有事件发生的 Channel,而是返回有事件发生的 Channel 对应的 SelectionKey
  • 具体的事件种类,有如下图所示的四种
    在这里插入图片描述

零拷贝

  • 零拷贝是网络编程的关键,常用的零拷贝有 mmap(内存映射) 和 sendFile
  • 零拷贝,是从操作系统的角度来说的,因为内核缓冲区之间,没有数据是重复的(只有 kernel buffer 有一份数据)
    在这里插入图片描述
  • mmap,用户空间可以共享内核空间的数据,就不用将文件内容拷贝到用户空间了,适合小数据量读写
    在这里插入图片描述
  • sendFile,内核空间中,修改后的数据直接复制到协议引擎,适合大文件传输
    在这里插入图片描述
  • NIO 使用零拷贝通过如图所示方法
    在这里插入图片描述

原生NIO存在的问题

在这里插入图片描述

线程模型

传统阻塞 I/O 服务模型

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

Reactor 模式

在这里插入图片描述

单 Reactor 单线程

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

单 Reactor 多线程

  • 其实就是将具体的业务逻辑交给线程池的线程执行
    在这里插入图片描述
    在这里插入图片描述

主从 Reactor 多线程

  • 其实就是将所有工作分成三个部分,接受连接请求并管理的Reactor 主线程 + 负责分发任务的 Reactor 子线程 + 负责执行业务逻辑的 Worker线程池
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

Netty 实现网络编程

在这里插入图片描述

Netty 的线程模型(架构)

  • Netty 主要基于主从 Reactor 多线程模型做了一定的改进,其中主从Reactor 多线程模型有多个 Reactor
  • Netty 抽象出两组线程池,类型都是 NioEventLoopGroup
    • BossGroup 专门负责接收客户端的连接,等同于 MainReactor
    • WorkerGroup 专门负责网络的读写,等同于 SubReactor
  • NioEventLoopGroup 相当于一个事件循环组, 这个组中含有多个事件循环 ,每一个事件循环是 NioEventLoop
    • 简单理解就是,NioEventLoopGroup 是一个线程池,里面包含很多 NioEventLoop,也就是一个个线程
  • NioEventLoop 表示一个不断循环的执行处理任务的线程, 每个 NioEventLoop 都有一个 selector , 用于监听绑定在其上的 socket 的网络通讯(Channel)
    • 这个不断循环,是指每次都执行相同的逻辑,但不是自己循环,而是事件触发每一次的执行

BossGroup

  • 每个BossGroup 中的 NioEventLoop 循环执行的步骤有3步
    • 轮询 accept 事件
    • 处理 accept 事件 , 与 client 建立连接 , 生成Channel , 并将其注册到 WorkerGroup 的某个 NIOEventLoop 上的 selector
    • 处理任务队列 TaskQueue 的任务 , 即 runAllTasks

WorkerGroup

  • 每个 WorkerGroup 中的 NIOEventLoop 循环执行的步骤
    • selector 轮询 read, write 事件
    • 针对每个触发 read, write 事件的 Channel,分别执行相应的 I/O 操作 和 逻辑处理
    • 处理任务队列 TaskQueue 的任务 , 即 runAllTasks

BossGroup 与 WorkerGroup

  • BossGroup 、WorkerGroup 实际上是 NioEventLoopGroup 类的实例
  • NioEventLoopGroup 是 EventLoopGroup 接口的实现类
    在这里插入图片描述
    在这里插入图片描述
  • 常用方法
//构造方法
public NioEventLoopGroup()
//断开连接,关闭线程
public Future<?> shutdownGracefully()

NioEventLoop

  • NioEventLoop 是
  • 针对 WorkerGroup 中的 NioEventLoop有如下特点
  • 每个 NioEventLoop 都有一个 selector,用于监听绑定在其上的 socket 网络通道(Channel)
  • NioEventLoop 内部采用串行化设计,从消息的读取->解码->处理->编码->发送,始终由 IO 线程 NioEventLoop 负责
  • 每个 Channel 都绑定有一个自己的 ChannelPipeline
  • 每个 NioEventLoop 都有一个 TaskQueue 任务队列,可以在 handler(ChannelHandler 实现类中的方法) 中添加异步任务 or 定时任务,但是因为 NioEventLoop 内部采用串行化设计,所以任务之间是串行化执行的
  • 对于耗时较长的操作,可以自定义线程池执行,不要添加到 NioEventLoop 中,特别是高并发,或追求高吞吐量的场景下

异步模型(ChannelFuture)

  • Netty 中的 I/O 操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个 ChannelFuture
  • 调用者并不能立刻获得结果,而是通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果
  • Netty 的异步模型是建立在 future 和 callback 的之上的
    在这里插入图片描述在这里插入图片描述
  • 简单来说,使用 Netty 的API,一般都是异步操作,会返回一个 ChannelFuture 实例,通过这个实例,可以添加 Listener ,其实就是一个 callback 方法
  • 常用的 Listener 为 ChannelFutureListener
// Netty server 端绑定接受请求的端口,这个绑定是一个异步操作,通过下面步骤可以在完成绑定后输出内容
serverBootstrap.bind(port).addListener(future -> {
	if(future.isSuccess()) {
		System.out.println(newDate() + ": 端口["+ port + "]绑定成功!");
	} else{
		System.err.println("端口["+ port + "]绑定失败!");
	}
});

Bootstrap、ServerBootstrap

  • Bootstrap 意思是引导,一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件
  • Bootstrap 类是客户端程序的启动引导类
  • ServerBootstrap 类是服务端程序的启动引导类
  • 常见的方法如下
//该方法用于服务器端,用来设置两个 EventLoop,BossGroup 、WorkerGroup 
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup)
//该方法用于客户端,用来设置一个 EventLoop
public B group(EventLoopGroup group) 
//该方法用来设置一个服务器端的通道 Channel 实现
public B channel(Class<? extends C> channelClass)
//用来给 Channel 添加配置,针对 BossGroup 
public <T> B option(ChannelOption<T> option, T value)
//用来给接收到的 Channel 添加配置,针对 WorkerGroup 
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value)
//该方法用来设置业务处理类即 自定义的 ChannelHandler 实现类,针对 WorkerGroup ,还有一个 handler(ChannelHandler handler) 针对 BossGroup 
public ServerBootstrap childHandler(ChannelHandler childHandler)
//该方法用于服务器端,用来设置占用的端口号
public ChannelFuture bind(int inetPort) 
//该方法用于客户端,用来连接服务器
public ChannelFuture connect(String inetHost, int inetPort) 

ChannelOption

  • Netty 在创建 Channel 实例后,一般都通过 ChannelOption 参数设置 Channel
  • ChannelOption 可以视为一个转为配置参数,参数配置类,作为 option(ChannelOption<T> option, T value)childOption(ChannelOption<T> childOption, T value)的入参
  • 常用的配置参数
    在这里插入图片描述

Channel

  • 不同协议、不同的阻塞类型的连接都有不同的 Channel 类型与之对应,常用的 Channel 类型如下
NioSocketChannel,异步的客户端 TCP Socket 连接
NioServerSocketChannel,异步的服务器端 TCP Socket 连接
NioDatagramChannel,异步的 UDP 连接
NioSctpChannel,异步的客户端 Sctp 连接
NioSctpServerChannel,异步的 Sctp 服务器端连接,这些通道涵盖了 UDP 和 TCP 网络 IO以及文件 IO

Selector

在这里插入图片描述

ChannelHandler 及其实现类

  • ChannelHandler 是一个接口,处理 I/O 事件或拦截 I/O 操作,并将其转发到其 ChannelPipeline(业务处理链)中的下一个处理程序
  • 对所有请求(Channel)的逻辑处理都是通过 ChannelHandler 的实现类完成的,ChannelHandler 的实现类是区分出站/入站的

出站/入站

  • 具体看请求的方向,如果方向是 Channel—>ChannelPipeline ,那就是入站
  • 如果是 ChannelPipelinel—>Channe,那就是出站
    在这里插入图片描述

ChannelHandler 实现类中的各种方法

  • ChannelHandler 实现类中的各种方法都是不同的事件触发并执行的
    • channelActive方法,通道就绪事件就会触发
    • channelRead方法,通道读取数据事件就会触发
    • channelInactive方法,通道断开事件就会触发
    • exceptionCaught方法,异常事件触发,可以用于发生异常后程序的善后处理,尽量不要影响到其它 Channel
    • userEventTriggered方法,当前的 ChannelHandler 的该方法 由 前面的 Netty 心跳检测机制 ChannelHandler 的触发
    • 还有很多,结合业务场景自定义重写

ChannelPipeline

  • ChannelPipeline 是一个 ChannelHandler 实现类的集合,它负责处理和拦截 inbound 或者outbound 的事件和操作,相当于一个贯穿 Netty 的链
  • ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel 中各个的 ChannelHandler 如何相互交互

常用方法

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

ChannelHandlerContext

  • 一个 Channel 包含了一个 ChannelPipeline,而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext组成的双向链表,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler
  • 入站事件和出站事件在一个双向链表中,入站事件会从链表 head 往后传递到最后一个入站的 ChannelHandler,出站事件会从链表 tail 往前传递到最前一个出站的 handler,两种类型的 ChannelHandler(inbound/outbound) 互不干扰
  • 保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象
  • ChannelHandlerContext 中包含一个具体的事件处理器 ChannelHandler ,同时 ChannelHandlerContext 中也绑定了对应的 ChannelPipeline 和 Channel 的信息,方便对 ChannelHandler进行调用
  • 常用方法
//关闭通道 Channel 
ChannelFuture close()
//刷新
ChannelOutboundInvoker flush()
//将数据写到 ChannelPipeline 中当前 ChannelHandler 的下一个 ChannelHandler 然后开始处理(出站)
ChannelFuture writeAndFlush(Object msg)

在这里插入图片描述

ChannelHandler 、ChannelPipeline、NioEventLoop、Channel 关系

  • ChannelHandler 充当了处理入站和出站数据的应用程序逻辑的容器
  • 实现ChannelInboundHandler接口(或ChannelInboundHandlerAdapter),可以接收入站事件和数据,这些数据会被业务逻辑处理
  • 同理,实现ChannelOutboundHandler接口(或ChannelOutboundHandlerAdapter),可以接收出站事件和数据,这些数据会被业务逻辑处理
  • 出站/入站要关注 ChannelHandler 在 ChannelPipeline 中的顺序,一般来讲, ChannelHandler 在 ChannelPipeline 中的顺序即为代码中往 ChannelPipeline 中添加 ChannelHandler 的顺序
  • 第一个添加的就是 ChannelPipeline 双向链表的头节点(head),最后一个添加的就是 ChannelPipeline 双向链表的尾节点(tail)
  • 出/入站的 ChannelHandler 都在同一个 ChannelPipeline 的双向链表中,编解码器的 ChannelHandler 一般作为 head,和第二节点
    • 因为入站的 ChannelHandler 执行顺序是 heap —>tail,出站的 ChannelHandler 执行顺序是 tail —> heap
    • 出/入站 ChannelHandler 之间的顺序并不互相影响,它们只是在同一个 ChannelPipeline 双向链表中连续相连,但是执行还是各按各的,即双向链表中的顺序同时包含了 出站/入站的 ChannelHandler 执行顺序,看出站顺序的时候只需要忽略掉链表中的入站 ChannelHandler ,反之看入站顺序亦然
  • 因为每个 NioEventLoop 都有自己的 select ,是一对一的关系,Channel 只能注册到多个 select 中的一个,所以一个 Channel 只能对应一个 NioEventLoop
  • 每个 NioEventLoop 都有一个 ChannelPipeline,所以 一个 Channel 对应一个 ChannelPipeline
  • 总结:每一个 Channel 都会有属于自己的 NioEventLoop 和 ChannelPipeline
  • NioEventLoop 的数量是有限的,Channel 的数量远大于 NioEventLoop 数量,所以多个 NioEventLoop 是按照固定的次序,被用来处理不断新加进来的 Channel ,NioEventLoop 每次处理新加进来的 Channel 都会为其初始化一遍,然后创建新的 ChannelPipeline

Unpooled 类

  • Netty 提供一个专门用来操作缓冲区(即Netty的数据容器)的工具类
  • 常用方法
//通过给定的数据和字符编码返回一个 ByteBuf 对象(类似于 NIO 中的 ByteBuffer 但有区别)
public static ByteBuf copiedBuffer(CharSequence string, Charset charset)
  • ByteBuf 不需要 flip,可以同时写入数据和读取数据,主要有三个成员属性
    • readerindex ,指明当前 ByteBuf 已经读取到的位置, 0—readerindex 已经读取的区域
    • writerIndex,指明当前 ByteBuf 已经写入的位置,readerindex—writerIndex 为可读的区域
    • capacity,整个 ByteBuf 的容量,单位是字节

Netty心跳检测机制

编码与解码

  • 编写网络应用程序时,因为数据在网络中传输的都是二进制字节码数据,在发送数据时就需要编码,接收数据时就需要解码
  • codec(编解码器) 的组成部分有两个:decoder(解码器)和 encoder(编码器)。encoder 负责把业务数据转换成字节码数据,decoder 负责把字节码数据转换成业务数据
  • Netty提供一系列实用的编解码器,他们都实现了 ChannelInboundHadnler 或者 ChannelOutboundHandler 接口
  • 在这些类中,channelRead 方法已经被重写了
  • 以入站为例,对于从 Channel 读取的数据,channelRead 方法会被调用。随后,它将调用由解码器所提供的 decode 方法进行解码,并将已经解码的数据转发给 ChannelPipeline 中的下一个 ChannelInboundHandler
  • 常用解码器 ByteToMessageDecoder
    在这里插入图片描述
  • 其它解码器
    在这里插入图片描述
  • 常用编码器 MessageToByteEncoder
    在这里插入图片描述
  • MessageToByteEncoder、ByteToMessageDecoder 之所以能成为常用的编/解码器,是因为它支持泛型,可以很简单直接重写 encode/decode方法实现自定义的编/解码器,这对解决 粘包/拆包 问题非常重要

TCP 粘包和拆包

  • TCP是面向连接的,面向流的,提供高可靠性服务
  • 收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发给接收端的包,更有效的发给对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包
  • 这样做虽然提高了效率,但是接收端就难于分辨出完整的数据包了,因为面向流的通信是无消息保护边界的
    在这里插入图片描述
  • 解决粘包和拆包,关键就是要解决服务器端每次应该读取的数据长度的问题, 这个问题解决,就不会出现服务器多读或少读数据的问题,从而避免的TCP 粘包、拆包
    • 解决方式:使用自定义协议 + 编解码器
    • 由上面引申出在确定协议和编解码器后就不会粘包、拆包,出现粘包、拆包就是因为没有使用已存在的协议和对应的编解码器,然后又没有自定义,导致使用 Netty 接收请求时,不知道一次正确的请求数据,应该读取多少字节

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

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

相关文章

RabbitMQ养成记 (3.MQ的简单工作模式 和 Pub/sub 订阅模式)

上一篇是一个简单的helloworld。 我们直接发直接收 这种是最简单的。 下面我们再来接触更加复杂一点&#xff1a; 简单工作模式 work queues 工作队列模式&#xff1a; 这里注意 这里的消息 对两个消费者 c1 c2来说是竞争关系 而不是等份分发关系&#xff0c; 就像两个线程…

[山海关crypto 训练营 day10]

日常鼓励自己&#xff1a;别抱怨努力的苦&#xff0c;那是你去看世界的路。 最近几天一直忙着项目的结项答辩&#xff0c;今天终于是搞完了&#xff0c;得到了老师们的一致好评&#xff0c;最近几天的努力也没白费&#xff01;现在可以愉快刷题了&#xff0c;先复现下LiteCtf的…

c++核心知识—文件操作

目录 一、文件操作 1、文本文件 2、二进制文件 一、文件操作 文件操作头文件&#xff1a;<fstream> 操作文件的三大流&#xff1a; 1、ofstream&#xff1a;写操作 2、ifstream&#xff1a;读操作 3、fstream&#xff1a;读写操作 1、文本文件 写文件 步骤&…

【数据结构】-学习链表所需要的预备知识

知识点收集于网络&#xff0c;我会加以总结&#xff0c;如果把预备知识学好了。那么后面的操作就不难了 用节或者结都可以&#xff0c;不要在意字的差别 目录 一、头指针与头结点的概念 二、链表带头结点和不带头节点的区别 三、八大链表类型&#xff1a; 四、链表节点为…

unity制作幽灵猎手射击游戏

文章目录 介绍人物向着鼠标点击的位置跑动、旋转lerp函数让摄像机平滑跟随敌人导航敌人攻击发射子弹攻击敌人玩家健康敌人健康分数显示刷怪笼游戏结束动画 介绍 玩家鼠标控制人物转向 玩家鼠标点击控制光线发射的终点 玩家受到伤害屏幕闪红 有三个怪物生成点 玩家射杀敌人获得分…

linux-项目部署软件安装

安装jdk 操作步骤&#xff1a; 1、使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux jdk-8u171-linux-x64.tar.gz 2、解压安装包&#xff0c;命令为tar -zxvf jdk-8u171-linux-x64.tar.gz -C /usr/local 3、配置环境变量&#xff0c;使用vim命令修改/etc/profile文…

【JavaWeb】-- Filter、Listener、Ajax、Vue

文章目录 Filter1.概述2.快速入门2.1 开发步骤2.2 代码演示 3.Filter执行流程4. Filter拦截路径配置5.过滤器链5.1 概述5.2 代码演示5.3 问题 Listener1.概述2. 分类3.代码演示 Ajax1.概述1.1作用1.2 同步和异步 2.快速入门2.1 服务端实现2.2 客户端实现2.3 测试 3.axios3.1 基…

“Shell“Awk命令

文章目录 一.Awk二.Awk按行输出文本三.Awk按字段输出文本四.通过管道&#xff0c;双引号调用shell命令五.总结&#xff1a; 一.Awk Awk的工作原理&#xff1a; 逐行读取文本&#xff0c;默认以空格或tab键为分隔符进行分隔&#xff0c;将分隔所得的各个字段保存到内建变量中&a…

康耐视智能相机IS2000与三菱PLC走MC协议通讯设置详细步骤及案例详解

1.IS2000(SLMP扫描界面)设置如下: 控制器类型:PLC型号 IP地址:PLC地址 主机端口:16进制下的PLC通讯端口 2、IS2000设备寻址界面设置如下: 六大控制块存放区域根据PLC设定,偏移量及设备数可更改。3.打开GX WORKS软件,选择新建工程,点击“确定”,界面如下: 4.点击“连…

初识redis【redis的安装使用与卸载】

一.redis的概念 Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库&#xff0c;并提供多种语言的API。在redis官网中对redis的描述是这样的&#…

MADDPG-学习笔记(1)

文献链接&#xff1a;https://arxiv.org/abs/1706.02275 "Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments"&#xff08;作者&#xff1a;Lowe, Ryan等人&#xff0c;2017年&#xff09; 环境搭建&#xff1a;https://zhuanlan.zhihu.co…

【保姆级教程】Windows安装CUDA及cuDNN

Windows安装CUDA及cuDNN 前言1. 第一次安装CUDA2. 第N次安装CUDA 一、 CUDA1. 查询CUDA版本2. 下载CUDA3. 安装CUDA4. 配置CUDA环境变量5. 检查CUDA是否安装成功 二、 cuDNN1. cuDNN版本的查询及下载2. 安装cuDNN3. 配置cuDNN的环境变量4. 检查cuDNN是否安装成功 三、查询CUDA及…

Linux常见指令理解

查看 Linux 主机 ip 在终端下敲 ssh[ip] ip 为刚才看到的 ifconfig 结果. 如果网络畅通, 将会提示输入用户名密码. 输入即可正确登陆 XShell 下的复制粘贴 复制: ctrl insert (有的 insert 需要配合 fn 来按) 粘贴: shift insert ctrl c / ctrl v 是不行的. Linu…

【C语言刷题——Leetcode10道简单题】

✨作者&#xff1a;平凡的人1 ✨专栏&#xff1a;《小菜鸟爱刷题》 ✨一句话&#xff1a;凡是过往&#xff0c;皆为序章 ✨说明: 过去无可挽回&#xff0c; 未来可以改变 今天是考四六级的日子&#xff0c;不知道大家考得怎么样呀&#xff1f;(反正我是寄了&#xff0c;好多没明…

Vue CLI ref props mixin plugin scoped

3.2. ref 属性 ref被用来给元素或子组件注册引用信息&#xff08;id的替代者&#xff09; 应用在html标签上获取的是真实DOM元素&#xff0c;应用在组件标签上获取的是组件实例对象vc使用方式 打标识&#xff1a;或获取&#xff1a;this.$refs.xxx <template> <di…

Python依据某一文件夹中大量文件的名称复制另一文件夹中的同名文件

本文介绍基于Python语言&#xff0c;针对一个文件夹下大量的Excel表格文件&#xff0c;基于其中每一个文件的名称&#xff0c;从另一个文件夹中找到与这一文件夹中文件同名的文件&#xff0c;并将找到的同名文件复制到第三个文件夹中的方法。 首先&#xff0c;我们来明确一下本…

【网络】深入浅出了解网络世界

HTTP协议 TCP/IP协议族 我们通常使用的网络&#xff0c;是在TCP/IP协议族上运作的。而HTTP协议就是TCP/IP内部的一个子集。 计算机与网络设备之间的通讯需要一定的规则&#xff0c;这种规则就称为协议。 TCP/IP就是互联网上各种协议的总称。 分层管理 TCP/IP 按层次分为…

架构活动中评估需求的五个关注点

从架构活动的整体目标出发&#xff0c;确认需求存在的必要性。很多时候&#xff0c;尤其是大的项目&#xff0c;需求方经常会夹带私货。虽然他们并没有什么恶意&#xff0c;但是这些附加的需求不仅会消耗研发资源&#xff0c;还会增加项目复杂度和规划难度。而最坏的情况&#…

【王道·计算机网络】第四章 网络层【未完】

一、 概述和功能 1.1 网络层功能 主要任务&#xff1a;把分组从源端传到目的端&#xff0c;为分组交换网上的不同主机提供通信服务传输单位&#xff1a;数据报功能&#xff1a; 路由选择与分组转发&#xff0c;即选择最佳路径异构网络互联(依靠路由器)拥塞控制(所有结点都来不…

会议日程——2023第十二届中国PMO大会

2023第十二届中国PMO大会 主题&#xff1a;拥抱变革 展现PMO力量 主办方&#xff1a;PMO评论 签到与入场&#xff1a;人脸识别 时间&#xff1a;6月17-18日 地点&#xff1a;北京蓝调庄园 【邀 请 函】 企业要基业长青就必须持续保持组织活力。企业的内外部环境不会一成不…