自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(136)
  • 资源 (6)
  • 收藏
  • 关注

原创 Netty底层原理

*每次发多少数据到网络中与当前网络的拥塞情况和服务端返回的TCP窗口的大小有关,涉及TCP的流量控制和拥塞控制,并且与Netty的反压有关。,它除了JDK自带的epoll模型的封装,还额外封装了一套,这两者都是epoll模型的封装,只是JDK的epoll模型是水平触发的,而Netty采用JNI重写的边缘触发。所谓背压,是进行流量控制的一种方案。TCP是面向字节流传输的协议,它把客户端提交的请求数据看作一连串的无结构的字节流,并不知道所传送的字节流的含义,也并不关心有多少数据流入TCP输出缓冲区中。

2023-11-12 22:16:09 502

原创 Java线程池——Executor框架

这个类适当地扩展了AbstractQueuedSynchronizer,以简化获取和释放围绕每个任务执行的锁。这可以防止中断,这些中断旨在唤醒等待任务的工作线程,而不是中断正在运行的任务。我们实现了一个简单的不可重入互斥锁,而不是使用ReentrantLock,因为我们不希望工作任务在调用setCorePoolSize等池控制方法时能够重新获得锁。此外,为了在线程实际开始运行任务之前抑制中断,我们将锁状态初始化为负值,并在启动时(在runWorker中)清除它。

2023-11-11 22:08:17 675

原创 Netty心跳检测

客户端的心跳检测对于任何长连接的应用来说,都是一个非常基础的功能。要理解心跳的重要性,首先需要从网络连接假死的现象说起。

2023-11-08 00:26:33 680

原创 Netty通道的容器属性Attribute

该方法的返回值为一个AttributeKey实例,它的泛型类型为实际上的key-value键值对中value的键值对中value的实际类型。可以通过AttributeMap的attr方法,根据key取得Attribute类型的value,然后根据value实例完成最终的两个重要操作:设置(set)和取值(get)。Netty中的Channel通道类,有类似于Map的容器功能,可以通过“key-value”键值对的形式来保存任何Java Object的值。

2023-11-07 15:46:22 232

原创 JSON和Protobuf序列化

因为像TCP和UDP这种底层协议只能发送字节流,因此当我们在开发一些远程过程调用(RPC)的程序时,需要将应用层的Java POJO对象序列化成字节流,数据接收端再反序列化成Java POJO对象。理论上对于性能要求不是太高的服务器程序可以选择JSON系列的序列化框架,而对于性能要求较高的服务器程序则应该选择传输效率更高的二进制序列化框架如Protobuf。

2023-10-30 22:49:18 750 1

原创 Netty编码器和解码器

OverrideSystem.out.println("解码出一个整数:" + i);@OverrideSystem.out.println("打印出一个整数:" + integer);使用上面的Byte2IngeterDecoder证书解码器需要先对ByteBuf的长度进行检查,如果有足够的字节,才进行整数的读取。这种长度的判断可以由Netty的ReplayingDecoder类来完成。

2023-10-28 18:47:24 436

原创 Netty基础入门和基本使用

这样就会导致一个结果@Sharable共享实例不是线程层面安全的,因此@Sharable共享的业务处理器,如果需要操作的数据不仅仅是局部变量,则需要进行线程的同步控制,以保证操作是线程层面安全的。出站处理用到的ByteBuf缓冲区一般是要发送的消息,通常由Handler业务处理器所申请而分配的,在每一个出站Handler业务处理器的处理完成后,最后数据包回来到出站的最后一棒HeadHandler,在数据输出完成后,ByteBuf会被释放一次,如果计数器为0,将被彻底释放掉。

2023-10-25 01:28:13 485

原创 Reactor反应器模式

这种模式的优点是解决了前面的新连接被严重阻塞的问题,在一定程度上极大地提高了服务器的吞吐量。而且线程的反复创建、销毁、线程的切换也需要代价。这种方法最大的问题就是如果前一个网络连接的处理没有结束,那么后面的连接请求没法被接收,于是后面的请求统统会被阻塞住,服务器的吞吐量就太低了。在单线程反应器模式中,Reactor反应器和Handler处理器都执行在同一条线程上(dispatch方法是直接调用run方法,没有创建新的线程),因此当其中某个Handler阻塞时,会导致其他所有的Handler都得不到执行。

2023-10-24 22:12:37 520

原创 Java NIO三大核心组件

*因为外部设备的读写设计到操作系统的中断,引入缓冲区可以减少频繁地与设备之间的物理交换,操作系统会对内核缓冲区进行监控,等待缓冲区达到一定的数量的时候(由内核决定,用户程序无需关心),再进行IO设备的中断处理,集中执行物理设备的实际IO操作。NIO中一个连接就是用一个Channel(通道)来表示,一个通道可以表示一个底层的文件描述符,例如硬件设备、文件、网络连接等,除此之外Java NIO的通道还可以更加细化,例如对应不同的网络传输协议类型,在Java中都有不同的NIO Channel实现。

2023-10-13 01:55:43 310

原创 x86的内存寻址方式

我们知道不同的进程之间看到的虚拟地址范围是一样的,所以多个进程下,不同进程的相同的虚拟地址可以映射不同的物理地址。即所有的段的基地址都是0,段长4G。所以说起来是分段,实际上等于没分了,再加上段的基地址全部是0,那进行地址翻译的时候,对于任何一个给定的逻辑地址,只需要看它的偏移量就可以知道它在内存中的位置,不需要去查找段描述符表和进行基址加偏移的运算。当进程需要内存时,从内核获得的仅仅是虚拟的内存区域,而不是实际的物理地址,进程并没有获得物理内存(物理页面),获得的仅仅是对一个新的线性地址区间的使用权。

2023-08-27 01:46:47 440

原创 CPU架构和指令集

地址总线的位数决定了CPU的寻址能力,它不一定和CPU位数相同,比如早期16位的CPU使用的是20位的地址总线,通过段地址的方式来实现20位的寻址。Intel从16位微处理器8086开始的整个CPU芯片系列,系列中的每种型号都保持与以前的各种型号兼容,主要有8086,8088(16位),80186,80286(过渡产品),80386,80486以及以后各种型号的Pentium芯片(32位CPU),通常所说的x86都是指32位CPU。x64是x86指令集的64位扩展,但它仍然兼容32位的x86指令集。

2023-08-26 21:53:41 495

原创 MySQL之深入InnoDB存储引擎——Undo页

TRX_UNDO_FSEG_HEADER:本UNDO页面链表对应的段的Segment Header信息(用于寻找INODE Entry)TRX_UNDO_PAGE_LIST:UNDO页面链表的基节点对于链表中的第一个页面,除了Undo Log Segment Header,在其下面还会有一个。

2023-08-09 21:09:49 337

原创 MySQL之深入InnoDB存储引擎——redo日志

我们知道数据的修改首先是在Buffer Pool中进行的,之后再定时刷到磁盘中。那么如果在事务提交后还没刷新到磁盘中,系统就崩溃了,那么此时数据就丢失了,这就不满足事务的持久性了。而如果我们考虑每次提交之后,都同步将事务中所有的页面刷新到磁盘,这样确实可以保证持久性,但是我们只是希望这个提交的事务的修改不会丢失,即使崩溃在重启后也可能进行恢复,那么其实完全没有必要在每次提交的时候就将页面全部刷回去,**只需要对修改的内容简单的做一个记录就可以了**。

2023-08-08 11:24:56 526

原创 MySQL之深入InnoDB存储引擎——Buffer Pool

以这个算法为核心,InnoDB维护了一个LRU链表,如果页不在Buffer Pool中,在把该页从磁盘加载到Buffer Pool的时候,就把该缓冲页对应的控制块作为节点添加到LRU链表的头部,如果使用到链表中的某个页时也将其移动到链表头部。在数据库中进行读取页的操作,首先将从磁盘读到的页存放在缓冲池中,这个过程称为将页“FIX”在缓冲池中,在下一次读取相同的页时,首先判断该页是否存在缓冲池中,如果存在则被命中,直接读取,否则读取磁盘上的页。当从磁盘上读取到一个页时,我们需要将其放置在空闲的缓冲页中。

2023-08-06 21:55:44 374

原创 MySQL查询执行计划详解(EXPLAIN)

如果被驱动表非常大,多次访问被驱动表可能导致很多次的磁盘IO(因为默认情况下是驱动表没找到一条记录就去查询被驱动表,如果被驱动表很大,那么可能会导致被驱动表前面引入的页面在后面被淘汰了,那么驱动表下一条记录进行连接时又要重新去磁盘中加载),因此引入join buffer,一次性读取多条驱动表记录放入其中。每个表都维护了一个变量,记录着对该表进行增删改的记录条数,**如果发生改动的记录数量超过了表大小的10%,并且自动重新计算统计数据的功能是打开的,那么服务器会重新计算一次统计数据。

2023-08-06 18:18:41 1734

原创 MySQL表空间结构与页、区、段的定义

前面我们讲到了区和段的概念,也讲到了它们对应的XDES Entry结构和INODE Entry结构以及各种以XDES Entry为节点的链表。我们知道了页的申请需要用到这些结构,那这些结构存放在那呢,这就需要了解整个表空间的结构了。表空间实际上就是由许许多多的页组成的,为了更好的管理页,我们引入了区的概念,对于16KB的页而言,64个连续的页面就是一个区。而**表空间可以看为是由若干个连续的区组成,其中每256个区被划分成了一组(同样是为了更好的管理),每个组中的前几个页面会负责维护这个组的一些信息。

2023-08-06 12:24:52 520

原创 MySQL处理客户端请求

MySQL的缓存系统会检测设计的每张表,只要该表的结构或者数据被修改,比如对表使用了Insert、Update、Delete、Truncate Table、Alter Table、Drop Table和Drop Database等语句,都会使得与该表有关的所有查询缓存无效并被删除。平时Web应用中一般会使用线程池进行数据库连接的管理,因为建立连接是需要时间的,对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接建立(如三次握手、验证账户、密码等)和释放过程的时间开销,从而缩减了系统整体响应时间。

2023-08-01 21:31:54 260

原创 MySQL之深入InnoDB存储引擎——物理文件

因为 MySQL 插件式存储引擎的体系结构的关系,MySQL 数据的存储是根据表的, 每个表都会有与之对应的文件。在 MySQL 8 之前不论表采用何种存储引擎,都有一个以 frm 为后缀名的文件,记录了该表的表结构定义。MySQL 8之后 InnoDB 存储引擎的表定义结构整合到 ibd 文件中,而 MyISAM 的 frm 文件变为 sdi 文件。

2023-07-29 00:23:36 390

原创 MySQL之深入InnoDB存储引擎——Checkpoint机制

它从 last Checkpoint 对应的 LSN 开始扫描 redo-log 日志,并将其应用到 buffer-pool 中,直到 last Checkpoint 对应的 LSN 等于 log flushed up to 对应的 LSN (也就是 redo-log 磁盘上存储的 LSN 值),则恢复完成。由于页的操作首先都是在缓冲池中完成的,那么如果一条DML语句改变了页中的记录,那么此时页就是脏的,即缓冲池中页的版本要比磁盘的新。那么数据库需要将新版本的页刷新到磁盘。所以 InnoDB 存储引擎。

2023-07-27 14:39:39 651

原创 深入TCP协议——tcp_tw_reuse和tcp_tw_recycle

我们已经知道TCP四次挥手中,主动方在收到被动方的FIN数据包之后会进入TIME_WAIT状态等待2MSL的时间后才进入CLOSED。在 Linux 操作系统下,TIME_WAIT 状态的持续时间是 60 秒,这意味着这 60 秒内,客户端一直会占用着这个端口,这是有一定的开销的。如果如果主动关闭连接方的 TIME_WAIT 状态过多,占满了所有端口资源,则会导致无法创建新连接。

2023-07-20 20:24:38 2704 1

原创 深入理解Linux网络——TCP协议三次握手和四次挥手详细流程

并且假如说节省第二次挥手的ACK包,那么因为下一个FIN的时间是不确定的,有可能很久,那么实现的时候得让FIN_WAIT_1等待一个很久的时间。如果是发生了如网络错误、断线或程序崩溃等错误或异常,那么自己这边的系统可能关闭所有的网络接口,释放所有的网络相关的内存等(取决于操作系统和协议栈的实现),而对端发送的保活数据包将接收不到ACK,重试几次后,就会进行连接的关闭,这个时候是不会进行四次挥手的。:等到一定时间后收不到服务端的反馈的时候来开启重传。每次超时时间为2的指数递增(1,2,4,8,16,32)

2023-07-20 17:49:40 381

原创 深入理解Linux网络——TCP连接的开销

*NUMA是一种针对多处理器系统的内存架构,其主要思想是将物理内存划分为多个节点,每个处理器可以直接访问所有的内存,但访问不同节点的内存的延迟和带宽可能会有所不同。**dentry对象的申请最终同样是是调用到了kmem_cache_alloc函数(对应的slab缓存dentry在内核初始化时的dcache_init中创建的),而file对象的申请最终是调用了kmem_cache_zalloc函数进行分配(对应的slab缓存flip是在内核初始化时的files_init中创建的)

2023-07-18 19:52:22 1284

原创 操作系统——虚拟内存管理

这些区域只是说把相同属性的数据集中放在一起,但实际上进程使用的地址是其在这个虚拟空地址间中的地址,而不是具体的堆、段等这些分区的偏移地址(这就是前面说到的和段式管理是不同层次的概念,段式管理中进程使用的数据地址是相对于段的偏移量,而这里的五个区域是段中自行划分的,只是一个抽象的概念)。在Linux系统中虽然保留了段机制,但是所有的程序的段地址都定死为0-4G,所以虽然逻辑地址和线性地址是两种不同的地址空间,但在Linux中逻辑地址就等于线性地址,它们的值是一样的(因为段基址为0)。

2023-07-16 21:54:47 778

原创 深入理解Linux网络——TCP连接建立过程(三次握手源码详解)

icsk->icsk_accept_queue定义在inet_connection_sock下,是一个request_sock_queue类型的对象,是内核用来接收客户端请求的主要数据结构。我们平时说的全连接队列、半连接队列全都是在这个数据结构里实现的。我们来看具体的代码。// 全连接队列 struct request_sock * rskq_accept_head;// 半连接队列 struct listen_sock * listen_opt;

2023-07-15 21:03:27 1622

原创 深入理解Linux网络——本机网络IO

上面路由表中10.143.x.y dev eth0是本机的局域网IP,虽然写的是dev eth0,但是其实内核在初始化local路由表的时候,把local路由表里所有的路由项都设置为了RTN_LOCAL。:__netif_receive_skb => __netif_receive_skb_core => deliver_skb,然后再将数据送入ip_rcv中进行后续操作。查找路由项的函数时ip_route_output_ports,它经过层层调用,来到关键的部分——fib_lookup。

2023-07-12 18:20:33 895

原创 深入理解Linux网络——内核是如何发送网络包的

调用dma_map_single函数创建内存和设备之间的DMA映射,tx_ring->dev是设备的硬件描述符,即网卡,skb->data是要映射的地址,size是映射的数据的大小,即数据包的大小,DMA_TO_DEVICE是指映射的方向,这里是数据将从内存传输到设备,返回的调用结果是一个DMA地址,存储在dma变量中,设备可以直接通过这个地址访问到skb的数据。这种设计的好处是,对于大的数据包,可以将其数据负载部分存储在分页区,避免对大块连续内存的分配,从而提高内存使用效率,减少内存碎片。

2023-07-12 01:41:34 1969 1

原创 深入理解Linux网络——内核与用户进程协作之多路复用方案(epoll)

epoll就是其中最优秀的实现方式,其提供了以下几个相关的函数:在用户进程调用epoll_create的时候,内核会创建一个struct eventpoll的内核对象,并把它关联到当前进程的已打开文件列表中。eventpoll的定义如下:wq:等待队列链表。软中断数据就绪的时候会通过wq来找到阻塞在epoll对象上的用户进程rbr:一棵红黑树,为了支持对海量连接的高效查找、插入和删除,eventpoll内部使用了一棵红黑树。通过这棵树来管理用户进程下添加进来的所有socket连接rdllist:就绪

2023-07-10 01:30:54 482

原创 深入理解Linux网络——内核与用户进程协作之同步阻塞方案(BIO)

我们自己的代码所在的进程:我们调用的socket()函数会进入内核态创建必要的内核对象。recv()函数会在进入内核态以后负责查看接收队列,以及在没有数据可以处理的时候把当前进程组色调,让出CPU。硬中断、软中断上下文:在这些组件中,将包处理完后会放到socket的接收队列中,然后根据socket内核对象找到其等待队列中正在因为等待而被阻塞掉的进程,将它唤醒。每次一个进程专门为了等待一个socket上的数据就被从CPU上拿出来,然后换上另一个进程。

2023-07-09 18:24:56 551

原创 深入理解Linux网络——内核是如何接收到网络包的

数据到来后的处理:1. 数据进入网卡Rx FIFO,通过DMA写入内存的RingBuffer,向CPU发起硬中断2. CPU响应硬中断,调用网卡启动时注册的中断处理函数3. 中断处理函数中将驱动传来的poll_list添加到CPU对应的softnet_data的poll_list,发起软中断4. 内核线程ksoftirqd发现软中断请求,关闭硬中断5. ksoftirqd线程根据软中断类型选择处理函数,调用驱动的poll函数收包6. poll函数摘下RIngBuffer上的skb,发到协议栈

2023-07-08 00:08:57 2433 6

原创 网络互联设备(集线器、交换机、路由器)

网桥(Bridge)工作在OSI模型的数据链路层,连接两个局域网,在各种传输介质中转发数据信号,扩展网络的距离,有效地限制两个介质系统中无关紧要的通信,选择性地转发数据帧,减少不必要的网络流量。由于交换机对多数端口的数据进行同时交换,这就要求具有很宽的交换总线带宽,如果二层交换机有N个端口,每个端口的带宽是M,交换机总线带宽超过N×M,那么这交换机就可以实现线速交换;另外,工作在数据链路层或更高层的设备如网桥、交换机、路由器等等,由它们连接起来的两组设备仍然分别处于各自独立的物理层,因此是两个网段。

2023-07-05 13:44:30 4430

原创 IP路由协议(RIP、IGRP、OSPF、IS-IS、BGP)

它首先检查的是掩码位数最长的,如果有32位掩码的路由条目,则这条路径会被优先检查,其次是24位、16位等等;三层交换方案通常在核心层使用三层交换机,汇聚层使用二层交换机,来自不同VLAN的信息流在二层交换机上汇聚,通过三层交换机相连的Trunk链路,在三层交换机实现路由,并转发给目的主机。OSPF有五种报文类型,每个OSPF包都具有OSPF数据包报头,IP包头中,协议字段为89,代表OSPF,组播地址=224.0.0.5或224.0.0.6。在实际的网络组建中会出现普通区域没有直接的链路和主干区域连接。

2023-07-02 16:57:06 2266 1

原创 路由协议基本术语

路由协议基本术语:自治系统、外部网关协议、内部网关协议、度量标准和度量值、管理距离、路由协议和路有环路问题

2023-07-01 20:14:26 394

原创 Windows编程课设(C#)——基于WPF和.net的即时通讯系统(仿微信)

一款参考QQ、微信的即时通讯软件。采用CS结构,客户端基于.Net与WPF开发,服务端使用Java开发。

2023-06-13 18:21:24 797

原创 操作系统相关问题——应用程序和操作系统怎么配合

是内核的代码而不是用户及程序在内核的代码,用户代码不可能在内核中存在,所以“用户态和内核态”是相对于CPU而言的。当应用程序陷入内核之后,自己已经下CPU了,以后发生的事情应用程序完全不知道,此时它的上下文环境已经被保存到了自己在内核态的的栈中了,CPU上运行的程序已经是内核程序。库中提供的函数其实都已经封装好了系统调用,需要下载源码才会看到。应用程序加上操作系统提供的功能才算是完整的程序,平时写的应用程序只能算是半成品,还需要调用操作系统提供的函数才能完整地做出一件事,而这些函数就是系统调用。

2023-05-07 16:41:28 537 3

原创 操作系统相关问题——软件是如何访问硬件的

显卡是显示器的适配器,CPU不直接和显示器交互,它只和显卡通信。显卡上有片内存叫显存,它映射到主机物理内存上的低端1MB的0xB8000-0xBFFFF。每个硬件都有自己的个性,操作系统不可能及时更新各种硬件的驱动方法(不可能刚出某个新硬件,OS开发者就开始为其编写驱动,这显然不现实)。,CPU访问外设就是访问IO接口,由IO接口将信息传给另一端的外设,也就是说CPU从来不知道有这些设备的存在,它只知道自己操作的IO接口。,这种映射让CPU访问外设的内存就如同访问主板上的物理内存一样。

2023-05-07 16:40:59 493

原创 系统调用与用户态陷入内核态

我们都知道操作系统中运行着很多的进程,如果普通的进程可以直接操作硬件那么这个系统的安全性没办法保障,所以操作系统分出了两种状态,一种状态是运行的代码可以操作硬件;一种状态不能操作硬件,只能切换到第一种状态去操作后再切换回来,这就是内核态和用户态。

2023-04-24 22:13:27 1655

原创 自定义OAuth2组件实现对授权码登录模式的封装

所谓OAuth2其实就是Open Authorization,即开放授权,是一种授权机制或者说是一种协议。OAuth2允许用户授权第三方应用访问其存储在开放平台(授权服务器)中的数据而不需要提供密码。授权服务器根据OAuth2协议标准制订一套授权的API,第三方网站接入开放平台之后即可通过其提供的API来实现用户授权和获取授权服务器中用户的信息的功能。

2023-04-14 00:43:15 1469 1

原创 HTTPS加密原理

既然非对称加密可以保证客户端发给服务端的信息只有服务端能读取,那么我们不难想到让客户端生成对称传输的密钥,然后用非对称加密中服务端发布的公钥对该密钥进行加密发给服务端,服务端收到之后用非对称加密中的私钥解密即可拿到对称加密的公钥。那么后续客户端生成密钥X再加密发出时其实使用的就是攻击者生成的公钥B去进行加密的,那么攻击者就可以通过自己的私钥B’解密出客户端生成的对称加密密钥X,然后再用服务端的公钥A加密后返回给服务端。对称加密,用一个密钥,对明文进行加密,同理,同这把密钥,也可以对密文进行解密。

2023-03-16 16:40:01 967

原创 MySQL基本组件与存储引擎

连接器:主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即使管理员修改了该用户的权限,该用户也是不受影响的。查询缓存:主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。

2023-03-14 01:01:18 191

原创 MySQL锁的分类和加锁机制

临键锁:行锁的一种算法,是记录锁和间隙锁的组合,会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住,再之它会把相邻的下一个区间也会锁住(可重复读默认使用的就是next key lock,但是对于唯一索引的查询则会降级为记录锁)记录锁:行锁的一种算法,只不过记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录,加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题,也避免了在修改的事务未提交前被其他事务读取的脏读问题;特点:粒度大,加锁简单,容易冲突;

2023-03-12 18:50:55 456

汇编大作业(课程设计):简易英英词典

用emu8086编写的实现简易英英词典功能的汇编程序 1. **单词及其英文解释的录入、修改和删除** - 录入新单词,把它插入到相应的位置(按词典顺序),其后跟英文解释、同义词、反义词;(*此功能要求在文件中完成,其它功能可以将单词放在数据段中*) - 可修改单词英文解释; - 删除单词及其英文解释; 2. **查找** - 输入不完整的字符串,会依顺序列出单词前缀和字符串相匹配的单词; - 如输入:en则列出:enable, enabled, enact等 - 查询某个单词英文解释(如enable: to provide with the means or opportunity; to make possible, practical, or easy),词库中不存在此单词,则提示找不到; - 查询某个单词的同义词(如accept: approve); - 查询某个单词的反义词(如win: lose); 3. **以上结果均需显示**

2022-06-02

Python大作业-音乐播放(基于爬虫+可视化+数据分析+数据库).rar

这是一个使用爬虫实现的音乐播放软件,使用数据库实现登陆注册功能,并对爬取数据实现可视化分析

2021-12-17

tomcat10+mysql5+mysql8+sqlyog+jdk8.zip

想要学习java后端开发web的必用工具

2021-10-10

SecureCRT64位.rar

SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或Linux服务器主机的软件。SecureCRT支持SSH,同时支持Telnet和rlogin协议。SecureCRT的SSH协议支持DES,3DES和RC4密码和密码与RSA鉴别,在今后的工作和学习中会经常的用到用来连接linux服务器。

2021-10-10

Linux系统镜像文件--CentOS-7-x86_64-Minimal-2009(免费)

想要安装Linux系统的可以下载试用,也可以安装在虚拟机上,主页同样有虚拟机软件资源共享

2021-10-10

基于vue实现的简易音乐播放软件

基于vue实现的简易音乐播放软件,实现了歌曲歌手搜索,评论显示以及歌词滚动功能,其中歌曲api已挂,只需要自己另寻一个api换上去即可正常使用

2021-09-27

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除