vs2017 如何做网站/网络营销网站推广
TCP流套接字编程
1. TCP & UDP 的区别
TCP 的核心特点是面向字节流,读写数据的基本单位是字节 byte
2 API介绍
2.1 ServerSocket
定义
ServerSocket 是创建 TCP 服务端 Socket 的API。
构造方法
方法签名 | 方法说明 |
---|---|
ServerSocket(int port) | 创建一个服务端流套接字Socket,并绑定到指定端口 |
所以服务器启动,需要绑定端口号
方法
方法签名 | 方法说明 |
---|---|
Socket accept() | 开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待 |
void close() | 关闭此套接字 |
2.2 Socket
- Socket 是客户端 Socket ,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
- 不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
构造方法
方法签名 | 方法说明 |
---|---|
Socket(String host, int port) | 创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接 |
这个方法的两个参数,都是服务器的IP & 端口,这个版本的构造方法,就是给客户端用的,服务器怎么通过这个类来构造对象呢?后续再来看;
方法
方法签名 | 方法说明 |
---|---|
InetAddress getlnetAddress() | 返回套接字所连接的地址 |
InputStream getlnputStream() | 返回此套接字的输入流 |
OutputStream getOutputStream() | 返回此套接字的输出流 |
TCP没有 send(),receive() 这样的操作,但是 TCP 调用 getlnputStream() 会得到个 InputStream 对象;调用 getOutputStream(),得到一个 OutputStream 对象,这两个对象是字节流对象;
虽然 Socket 自身没有读写操作,但是 Socket 可以拿到字节流对象,就可以通过字节流对象,来进行读写操作;
3. 通过TCP实现回显服务器
TCP Echo Server
创建关联对象
通过构造方法,绑定关联的端口号 (和 UDP类似,都是在构造对象的时候,绑定端口号)
实现 start()
处理客户端发送的连接
TCP 和 UDP 服务器 start() 的主循环的第一步有所区别:
- UDP 进入主循环,就可以直接处理请求,根据请求计算响应,把响应返回客户端;
- TCP服务器 ,进入主循环后,因为 TCP 是有连接的,所以第一步是先处理客户端发来的连接;
- 这个连接就类似于打电话,在客户端打电话给服务器时,服务器要先接通电话,才可以进行后续的正常通信;
所以TCP服务器进入主循环的第一步,就是进行接通电话的操作,而拨号操作,是客户端来完成的;
调用 ServerSocket 对象底下的 accept() 方法,起到接听电话的作用;
还需要接收 accept() 方法的返回值:
- 如果客户端和服务器确实已经建立连接了,那 accept() 是可以拿到这个请求连接的;
- 如果客户端没有发起连接,那么 accept() 就会产生阻塞 ,和前面的 receive() 类似;
TCP 服务器后续通过对clientSocket 进行读写数据,来和客户端进行通信;
进一步理解 ServerSocket 和 Socket 的职责划分
处理一个客户端的连接
处理连接的过程比较复杂,因此我们把这个操作封装成一个方法;
可能会涉及到多个客户端的请求和响应,如果服务器接收到多个请求,就要返还给客户端多个响应;
服务器与客户端成功连接,打印日志:
这两个方法可以拿到对端(客户端)的 IP & 端口号;
获取输入流对象&输出流对象
打印出客户端的IP&端口号后,就需要进一步地处理客户端的请求和响应,需要借助 Socket 类内置的 InputStream & OutputStream 来处理这些请求和响应
这里获取到的是输入流对象,后续提供这个对象,来读取客户端的请求;
接下来获取输出流对象,并且处理异常:
拿到输入流对象&输出流对象后,后续读取请求,就使用输入流对象;返回响应,就把响应的内容写入输出流对象中;
接下来,在 try 的代码块中,实现读取请求和返回响应的操作,这些操作分成三步
- 读取请求并解析
- 根据请求计算响应
- 返回响应给客户端
因为在一次连接中,这三个操作可能会解析多次,所以我们提供 while 循环来处理
读取请求
下列操作,读取到的请求是一个字节数组,还需要手动把字节数组再转成字符串,才方便后续的处理和打印:
我们可以借助 Scanner 来进行更简单直接的读取操作,既可以读请求,读出来的请求又已经是一个字符串;
- 把刚刚从 Socket 中拿到的 InputStream 填入 Scanner 中,后续通过 Scanner 直接读取请求中的内容;
- 如果 Scanner 没有再读取到数据,说明连接断开,就可以结束循环了
所以读取请求,可以直接借助 read(),也可以借助 Scanner 来辅助完成
补充
- Scanner 可以控制处理台输入,又可以控制处理文件的输入,还可以控制处理网络的输入;
- Scanner 的构造方法:
- Scanner 的构造方法,填入的是一个InputStream 对象
根据请求计算响应
- 当前编写的是一个回显服务器代码,所以可以直接在计算响应的逻辑返回请求即可
返回响应给客户端
下列写法,会直接拿到 response 中的字节数组,然后通过 outputStream 提供的 write(),来写入输出流对象即可;
这种计算响应的方法,是提供字节的方式填充输出流对象;
除了上述写法,我们还可以利用字符流的方式:
这里的 writer 和 System.out 起到的的效果类似,所以 println,printf 等等都可以通过调用
打印返回响应的日志和连接断开的日志
服务器一次连接可处理多个请求的原理
服务器 start() 的代码块中, process() 方法处理请求返回响应的逻辑,相当于嵌套了两层 while 循环:
因此,可以在服务器与客户端的一次连接中,服务器处理多个请求;
如果在一次连接中,客户端发送多次请求,服务器就返还多个响应(打一次电话可以说一句话或者很多句话);
补充
- 一个连接一个请求(短连接),一个连接多个请求(长连接);
- 因为连接过程的开销非常大,所以在日常开发中,更主流的是长连接,一个连接处理多个请求;
- 就好比锁消除,针对要加锁的多个逻辑,每个逻辑都进行加锁,开销非常大,所以更科学的做法是把这些逻辑合在一起,只进行一次加锁;(和领导汇报工作成果,应该在一次电话中一次性汇总完毕,而不是打多次电话。每次电话只汇报一个成果)
TCP Echo Client
创建 Socket 对象
Socket 在客户端和服务器都可以使用,服务器的 Socket 通过调用accept()拿到,但是客户端的 Socket 就需要通过实例来创建对象;
实现客户端构造方法
在客户端的构造方法中,传入服务器的IP和端口号;
传到构造方法中的字符串IP地址(类似127.0.0.1这样的字符串),不需要任何转换;
对比UDP 的客户端,TCP客户端在构造方法在实例Socket对象后,就会在底层和对端建立TCP连接,连接好后,服务器会记录对端的信息(实例化Socket对象时传入的IP和端口号);
因此,服务器的IP和端口号,在TCP客户端中就不需要再创建变量来保存了;
从控制台中读取请求,发送给服务器
从控制台中读取用户输入信息作为请求
为了实现客户端能够和服务器在一次连接的情况下,发送多次请求,我们设置一个循环:
这步操作可以读取刚刚输入控制台的一行信息,读取到的信息作为客户端的请求;
拿到输入流&输出流
之后就把这个请求写入 Socket 对象中,写的时候也需要拿到Socket对象的 InputStream 输入流& OutputStream 输出流;
为了使用方便,可以对拿到的输入流和输出流再套一层壳
完善循环逻辑
所以在主循环中,第一步操作是从控制台中读取用户输入,把读取到的输入设置为请求:
第二步就是把请求发送给服务器
第三步,就是读取服务器返回的响应,并且把读取到的响应打印到控制台
客户端与服务器交互过程
区分客户端与服务器的 Socket 对象
下列服务器和客户端的两个 socket 对象,分别在不同进程中,甚至在不同主机中,因此绝对不是同一个对象;
这两个对象存在密切的关联关系,可以把这两个 socket 对象理解为两部电话:
- 接通这两部电话后,从A听筒说话,B可以听见;从B听筒说话,A可以听见(从一边对Socket对象写数据,另一边的 Socket 对象就可以读到);
- 但是这两个对象绝对不是同一部电话;
处理细节问题
问题一:冲刷缓冲区
完善 main 方法
程序运行结果
关掉客户端:
再启动一次客户端,并且发送一个数据,并且一敲回车,发现没有反应:
为什么没有反应呢?因为其实刚刚客户端代码,并没有真的把请求发送出去:
这个操作只是把数据放到 “发送缓冲区” 中,还没有真正写入网卡里;
- 发送缓冲区其实就是一块内存空间,对网络/硬盘写数据是一个非常低效的操作,如果频繁地调用这些比较低效的操作,程序运行是非常缓慢的;
- 为了提高效率,就引入一个内存缓冲区,把要写入的数据都放入缓冲区中,再统一进行发送,这样可以减小写硬盘和写网络的次数;
- 但是提高效率的同时,也会产生副作用,就是调用 writer.println 这样的操作,并没有真正地触发发送数据操作,而只是把数据写入缓冲区;
- 当然,把数据写入缓冲区,而不是直接发送这样的行为,是 PrintWriter的行为,如果不套壳,是可以直接发送的;
- 但是在实际开发中,广泛使用了缓冲区这样的概念,调用flush()来刷新缓冲区这个操作是非常关键的;
如何真正地把数据发送出去呢?我们要使用刷新操作(调用 flush() 方法来冲刷缓冲区),把缓冲区的数据强制写入 IO 设备中:
客户端服务器交互结果
问题二:针对 hasNext 对一个完整请求/响应设置标识符
println 的操作,会自动加上一个 \n :
但是如果在这个代码中不加这个 \n,直接使用 print行不行呢?
我们重新启动一下客户端,并且发送内容,发现客户端又没有反应了,并且服务器也没有读到信息:
造成上述原因,是因为 next() 的问题,修改成 print 后,客户端输入的数据也是发送到服务器上了,并且服务器也收到了,但是服务器并没有真正处理,因为服务器有一个hasNext()判断:
补充
- hasNext() 的行为是,判断当前收到的数据是否包含“空白符”,什么是空白符呢?
- 换行,回车,空格,制表符,翻页符......都是空白符;
- 遇到空白符,hasNext()才会认为是一个完整的 next,否则在遇到空白符之前,hasNext() 都会阻塞。
所以刚刚在修改成 print 之后,发送的内容是不包含空白符的内容,hasNext() 就会阻塞而无法进入下面读取请求的逻辑;
总结
- 使用 println,是在约定一个请求/响应,是在使用 \n 作为结束标记,对端在读取数据的时候,也会在读取到 \n 时,判断读取到一个完整的请求/响应;
- 这是我们在使用TCP时,特别需要注意的事项,并且和UDP不一样;
- UDP是以 DatagramPacket 作为单位的,但是TCP则是以字节为单位,但是实际上一个请求,往往是以多个字节构成的;
- 到底多少个字节为一个完整的请求/响应,就需要程序员想办法标记出来,引入分割符是标记一次完整请求/响应的典型方式,不一定是换行,也可以是其他分割符;
问题三:根据不同Socket的生命周期判断是否需要手动关闭
在TCP服务器刚刚编写的代码中,涉及两种Socket:
- ServerSocket的生命周期,贯彻整个服务区进程,不需要手动关闭
- clientSocket 的生命周期是一次连接,而不是整个服务器进程;
- 所以每个客户端连接,都会创建一个新的 clientSocket,每个客户端断开,这个对象就应该 close() 了,但是当前代码并没有对 clientSocket 进行 close() 释放;
- 没有在每次连接结束后,对 clientSocket 进行关闭,就会造成文件资源泄漏的问题(文件一直在打开,而不进行关闭,在打开到一定程度,会把文件描述表耗尽,就无法继续打开新文件)
- 在 poccessConnection() 方法的逻辑执行完毕之后,我们就可以对 clientSocket 进行关闭
总结
- 对于是否需要手动关闭 Socket ,需要我们分析请求它的生命周期是跟随整个进程,还是跟随某个环节;
- 如果是跟随整个进程,那么可以不手动关闭 Socket;如果是每个请求都会创建应该 Socket,或者每一次连接都会创建一个 Socket,或者某一个环节的执行周期,会创建一个Socket,这样的情况,就需要我们手动关闭 Socket;
问题四:服务器无法同时等待 accept() &等待已连接的客户端发送响应
一个服务器能同时给多个客户端提供服务,那么刚刚编写的TCP服务器也可以处理多个请求吗?我们关掉客户端,再重新启动多个客户端:
补充:修改同时启动多个客户端的IDEA设置
IDEA 会默认只启动一个客户端,再启动别的客户端,会先关闭上一个启动的客户端;我们通过这里的设置,就可以让 IDEA 启动多个客户端;
设置好后,我们再来重新启动两个客户端, 并且先后发送请求:
结果在第二个客户端发送请求时,又卡住了,并且第一个创建的客户端多次发送请求的操作是没问题的,服务器都会有一个正常响应,但是第二个客户端无论怎么发送请求,都不会有响应:
并且我们通过服务器日志,可以发现,在第二个客户端上线时,并没有再次打印日志;
如果我们关掉第一个客户端,第二个客户端发送的请求,会马上被服务器接收,并且返回响应
所以当前代码,TCP服务器在同一时刻,只能处理一个客户端发送的请求;
针对上面出现的问题,我们对服务器的处理请求,返回响应这一块代码的关键逻辑进行分析:
如果同一时刻,有多个客户端对一个服务器进行连接,那么第一个和服务器连接的客户端1:
所以当前这个服务器代码,如果已经在处理一个客户端的请求,就没办法处理另一个客户端的请求,服务器代码会卡在循环中,无法重新调用 accept()连接新的服务器,直到连接的客户端退出,导致循环终止;
总结
- 当前服务器代码,无法同时等待 accept 和 等待用户请求;在等待客户端发送请求的时候,没办法等待 accept() ,这个时候,如果有新的客户端连接,也无法接听电话(一个专业销售没办法在给先来的顾客讲解产品的时候,又去接待低级销售后面揽入店的顾客);
- 因此,服务器的代码,导致服务器一次只能处理一个客户端发送的请求,这个代码是不合理的;
4. 服务器引入多线程
如果只是单个线程,无法同时响应多个客户端;为了解决这个问题,此处给每个客户端都分配一个线程;
在服务器主线程中,就只是进行 accept(),每次有新的客户端 accept() 连接成功,就创建一个新的线程,又新线程负责完成,后续对客户端 Socket 对象的引用 clientSocket 的读写操作;
引入线程之后,重新启动服务器和两个客户端,可以发现服务器打印了两个带着不同端口号的日志;
因此,在引入线程之后,服务器可以一边等待请求,一边等待 accept() 连接新的客户端;
5. 服务器引入线程池
客户端连接,服务器就会创建新线程,客户端断开连接,客户端就会销毁线程,为了避免频繁创建销毁线程,也可以引入线程池;
线程池
对于在服务器引入线程池,一般不会使用 newFixedThreadPool,因为会创建一个固定线程数的线程池,意味着同时处理的客户端连接数目就固定了;
把任务都交到线程池中,线程池已经预先创建好了一些线程,提前创建好的线程就可以立刻投入工作,从而减少再去创建线程的开销;
线程不是越多越好,如果线程数量过多,CPU的利用率无法再被提高,还会导致系统调度速度下降;并且创建线程也是需要系统资源的,系统总体资源是有限的(一个主机差不多只能创建几千个线程);
无论是多线程,还是线程池,一个线程都对应一个客户端,并且一个主机创建的线程数目是有上限的,那如果有成千上万个客户端,同时访问一个服务器(一台主机),该怎么办呢?
IO多路复用/IO多路连接(这里不重点讲解,因为JVM中没有原生的 IO 多路复用 API,而是把API重新封装,已经不仅仅是多路复用了,后续会详细讲解针对 Java 的 IO多路复用所使用的 NIO,Netty 等知名网络框架,当前讲的IO是 BIO/Blocking IO);
扩展
基于BIO(同步阻塞IO)的长连接会一直占用系统资源。对于并发要求很高的服务端系统来说,这样的消耗是不能承受的。
- 由于每个连接都需要不停的阻塞等待接收数据,所以每个连接都会在一个线程中运行。
- 一次阻塞等待对应着一次请求、响应,不停处理也就是长连接的特性:一直不关闭连接,不停的处理请求。
实际应用时,服务端一般是基于NIO(即同步非阻塞IO)来实现长连接,性能可以极大的提升。
6. 长短连接
TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接;
长连接和短连接的概念
- 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
- 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。
长连接和短连接区别
- 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
- 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
- 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。
相关文章:

【JavaEE初阶 — 网络编程】实现基于TCP协议的Echo服务
TCP流套接字编程 1. TCP & UDP 的区别 TCP 的核心特点是面向字节流,读写数据的基本单位是字节 byte 2 API介绍 2.1 ServerSocket 定义 ServerSocket 是创建 TCP 服务端 Socket 的API。 构造方法 方法签名 方法说明 ServerS…...

vue结合canvas动态生成水印效果
在 Vue 项目中添加水印可以通过以下几种方式实现: 方法一:使用 CSS 直接通过 CSS 的 background 属性实现水印: 实现步骤 在需要添加水印的容器中设置背景。使用 rgba 设置透明度,并通过 background-repeat 和 background-size…...

Qt 5 中的 QTextStream 使用指南
文章目录 Qt 5 中的 QTextStream 使用指南介绍基本概念读取文件注意事项结论 Qt 5 中的 QTextStream 使用指南 介绍 QTextStream 是 Qt 框架中用于处理文本数据的类。它提供了方便的接口来读写文本文件或字符串,支持多种编码格式,并且可以与 QIODevice…...

中安证件OCR识别技术助力鸿蒙生态:智能化证件识别新体验
在数字化和智能化的浪潮中,伴随国产化战略的深入推进,国产操作系统和软件生态的建设逐渐走向成熟。鸿蒙操作系统(HarmonyOS Next)作为华为推出的重要操作系统,凭借其开放、灵活和高效的特点,正在加速在多个…...

SpringBoot 框架下基于 MVC 的高校办公室行政事务管理系统:设计开发全解析
2系统开发环境 2.1vue技术 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。 [5] 与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第…...

【ArkTS】使用AVRecorder录制音频 --内附录音机开发详细代码
系列文章目录 【ArkTS】关于ForEach的第三个参数键值 【ArkTS】“一篇带你读懂ForEach和LazyForEach” 【小白拓展】 【ArkTS】“一篇带你掌握TaskPool与Worker两种多线程并发方案” 【ArkTS】 一篇带你掌握“语音转文字技术” --内附详细代码 【ArkTS】技能提高–“用户授权”…...

Selenium3+Python如何操作键盘
selenium操作键盘,需要导入Keys类:“from selenium.webdriver.common.keys import Keys” 调用键盘操作的快捷键的方法 : 单键值:直接传入对应的键值“element.send_keys”(快捷键的键值) 组合键:键值之间由逗号分隔…...

PLC协议
PLC协议通常指的是可编程逻辑控制器(Programmable Logic Controller, PLC)与其他设备之间通信时所使用的协议。PLC广泛应用于工业自动化领域,用于控制和监控设备。不同厂商和应用场景可能使用不同的通信协议。 常见的PLC通信协议 1. Modbus …...

C_字符串的一些函数
1.字符串输入函数 scanf("%s",数组名); gets(数组名); 区别: scanf(“%s”,数组名); 把空格识别为输入结束 #include <stdio.h>int main() {char a[10];printf("输入:");scanf("%s",a)…...

使用Native AOT发布C# dll 提供给C++调用
Native AOT,即提前本地编译(Ahead-Of-Time Compilation),是一种将托管代码(如 C#)编译为本机可执行文件的技术,无需在运行时进行任何代码生成。 (Native AOT 优缺点截图摘自张善友博…...

Git 提交代码日志信息
前言 在项目中经常用到git提交代码,每次提交时需要添加日志信息,那么一套规范的日志信息会让整个git仓库看起来赏心悦目! 以下是Git 提交代码日志信息的建议: 一、格式规范 标题(Subject) 标题是日志信息中…...

Request method ‘POST‘ not supported(500)
前端路径检查 查看前端的请求路径地址、请求类型、方法名是否正确,结果没问题 后端服务检查 查看后端的传参uri、传参类型、方法名,结果没问题 nacos服务名检查 检查注册的服务是否对应(我这里是后端的服务名是‘ydlh-gatway’,服务列表走…...

终端环境下关闭显示器
终端环境下关闭显示器 使用vbetool vbetool 使用 lrmi 来运行视频 BIOS 中的代码。目前,它能够更改 DPMS 状态、保存/恢复视频卡状态并尝试从头开始初始化视频卡。 vbetool dpms off...

常见排序算法总结 (三) - 归并排序与归并分治
归并排序 算法思想 将数组元素不断地拆分,直到每一组中只包含一个元素,单个元素天然有序。之后用归并的方式收集跨组的元素,最终形成整个区间上有序的序列。 稳定性分析 归并排序是稳定的,拆分数组时会自然地将元素分成有先后…...

【后端开发】Go语言编程实践,Goroutines和Channels,基于共享变量的并发,反射与底层编程
【后端开发】Go语言编程实践,Goroutines和Channels,基于共享变量的并发,反射与底层编程 【后端开发】Go语言高级编程,CGO、Go汇编语言、RPC实现、Web框架实现、分布式系统 文章目录 1、并发基础, Goroutines和Channels2、基于共享…...

PyTorch 2.5.1: Bugs修复版发布
一,前言 在深度学习框架的不断迭代中,PyTorch 社区始终致力于提供更稳定、更高效的工具。最近,PyTorch 2.5.1 版本正式发布,这个版本主要针对 2.5.0 中发现的问题进行了修复,以提升用户体验。 二,PyTorch 2…...

【Android】组件化嘻嘻嘻gradle耶耶耶
文章目录 Gradle基础总结:gradle-wrapper项目根目录下的 build.gradlesetting.gradle模块中的 build.gradlelocal.properties 和 gradle.properties 组件化:项目下新建一个Gradle文件定义一个ext扩展区域config.gradle全局基础配置(使用在项目…...

vulnhub靶场【哈利波特】三部曲之Aragog
前言 使用virtual box虚拟机 靶机:Aragog : 192.168.1.101 攻击:kali : 192.168.1.16 主机发现 使用arp-scan -l扫描,在同一虚拟网卡下 信息收集 使用nmap扫描 发现22端口SSH服务,openssh 80端口HTTP服务,Apach…...

HarmonyOS开发中,如何高效定位并分析内存泄露相关问题
HarmonyOS开发中,如何高效定位并分析内存泄露相关问题 (1)Allocation的应用调试方式Memory泳道Native Allocation泳道 (2)Snapshot(3)ASan的应用使用约束配置参数使能ASan方式一方式二 启用ASanASan检测异常码 (4)HWASan的应用功能介绍约束条件使能HWASan方式一方式…...

java调用ai模型:使用国产通义千问完成基于知识库的问答
整体介绍: 基于RAG(Retrieval-Augmented Generation)技术,可以实现一个高效的Java智能问答客服机器人。核心思路是将预先准备的问答QA文档(例如Word格式文件)导入系统,通过数据清洗、向量化处理…...

2023年第十四届蓝桥杯Scratch国赛真题—推箱子
推箱子 程序演示及其源码解析,可前往: https://www.hixinao.com/scratch/creation/show-188.html 若需在线编程,在线测评模考,助力赛事可自行前往题库中心,按需查找: https://www.hixinao.com/ 题库涵盖…...

银河麒麟V10-SP1设置redis开机自启
前言: redis安装请看:银河麒麟V10-SP1离线安装redis5.0.1_银河麒麟v10 redis5.0-CSDN博客 一、编辑自启文件 vim /etc/systemd/system/redis.service [Unit] DescriptionRedis In-Memory Data Store Afternetwork.target [Service] Typeforking ExecS…...

释放超凡性能,打造鸿蒙原生游戏卓越体验
11月26日在华为Mate品牌盛典上,全新Mate70系列及多款全场景新品正式亮相。在游戏领域,HarmonyOS NEXT加持下游戏的性能得到充分释放。HarmonyOS SDK为开发者提供了软硬协同的系统级图形加速解决方案——Graphics Accelerate Kit(图形加速服务…...

Node.js 实战: 爬取百度新闻并序列化 - 完整教程
很多时候我们需要爬取一些公开的网页内容来做一些数据分析和统计。而多数时候,大家会用到python ,因为实现起来很方便。但是其实Node.js 用来爬取网络内容,也是非常强大的。 今天我向大家介绍一下我自己写的一个百度新闻的爬虫,可…...

106.【C语言】数据结构之二叉树的三种递归遍历方式
目录 1.知识回顾 2.分析二叉树的三种遍历方式 1.总览 2.前序遍历 3.中序遍历 4.后序遍历 5.层序遍历 3.代码实现 1.准备工作 2.前序遍历函数PreOrder 测试结果 3.中序遍历函数InOrder 测试结果 4.后序遍历函数PostOrder 测试结果 4.底层分析 1.知识回顾 在99.…...

qt QToolButton详解
1、概述 QToolButton是Qt框架中的一个控件,它继承自QAbstractButton。QToolButton通常用于工具栏(QToolBar)中,提供了一种快速访问命令或选项的方式。与普通的QPushButton按钮相比,QToolButton通常只显示一个图标而不…...

2024年大热,Access平替升级方案,也适合Excel用户
欢迎各位看官,您来了,就对了! 您多半是Access忠实粉丝,至少是excel用户,亦或是WPS用户吧。那就对了,今天的分享肯定对您有用。 本文1100字,阅读时长2分50秒! 现实总是不尽人意&am…...

探索Scala的模式匹配:身份证识别与等级判定!!! #Scala # scala #匹配模式
在Scala编程语言中,模式匹配是一个强大且表达力丰富的特性,它允许我们以声明式的方式处理多种情况。今天,我们将通过两个有趣的例子来展示Scala模式匹配的魅力:身份证号识别和等级判定。 1. 身份证号识别:定位你的家乡…...

python数据分析之爬虫基础:爬虫介绍以及urllib详解
前言 在数据分析中,爬虫有着很大作用,可以自动爬取网页中提取的大量的数据,比如从电商网站手机商品信息,为市场分析提供数据基础。也可以补充数据集、检测动态变化等一系列作用。可以说在数据分析中有着相当大的作用!…...

【星海随笔】syslinux
Ubuntu相关资料 https://www.pugetsystems.com/labs/hpc/ubuntu-22-04-server-autoinstall-iso/#Step_2_Unpack_files_and_partition_images_from_the_Ubuntu_2204_live_server_ISO https://launchpad.net/ubuntu/source/squashfs-tools/1:4.6.1-1build1 sudo tar -xf my_compu…...