2. 网络之网络编程

网络编程

文章目录

  • 网络编程
  • 1. UDP
    • 1.1 DatagramSocket
      • 1.1.1 DatagramSocket 构造方法
      • 1.1.2 DatagramSocket 方法:
    • 1.2 DatagramPacket
      • 1.2.1 DatagramPacket构造方法
      • 1.2.2 DaragramPacket方法
      • 1.2.3InetSocketAddress API
    • 1.3 UDP回显服务器
      • 1.3.1 框架结构
      • 1.3.2 读取请求并解析
      • 1.3.3 根据请求构建响应
      • 1.3.4 响应发回客户端
      • 1.3.5 打印日志
      • 1.3.6 完整程序
    • 1.4 UDP回显客户端
      • 1.4.1构建框架
      • 1.4.2 控制台读取数据构建请求
      • 1.4.3 发送请求
      • 1.4.4 接收响应
      • 1.4.5 输出响应
      • 1.4.6 完整代码
  • 2. TCP
    • 2.1 ServerSocket
      • 2.1.1ServerSocket 构造方法
      • 2.1.2 ServerSocket 方法
    • 2.2 Socket
      • 2.2.1 Socket 构造方法
      • 2.2.2 Socket 方法
    • 2.3 UDP回显服务器
    • 2.4 UDP回显客户端
  • 3. UDP和TCP的异同
    • 3.1 异
    • 3.2 同
  • 4. 部署至云服务器
    • 4.1 打包
    • 4.2 上传
    • 4.3 执行
    • 4.4 问题总结:

    网络编程是使用 IP地址,或域名,和 端口连接到另一台计算机上对应的程序,按照规定的 协议 (数据格式)来交换数据,实际编程中建立连接和发送、接收数据在语言级已经实现,做的更多的工作是设计协议,以及编写生成和解析数据的代码罢了,然后把数据转换成逻辑的结构显示或控制逻辑即可。

    网络编程的三要素

  • IP 地址: 用于标识网络设备的网络地址。
  • 端囗: 应用程序在设备中唯一的标识,对不同应用程序进行区分。
  • 协议:数据在网络中传输(传输层)的规则,其中最主要的UDP协议和TCP协议。
    • TCP:用户传输协议
    • UDP:用户数据报协议

    我们这里的重点不在于介绍UDP、TCP协议的内容,而是关注Java中使用UDP、TCP协议(传输层)进行数据传输,并且通过这两个传输层协议完成基础的回显服务器、客户端的编写

1. UDP

1.1 DatagramSocket

    DatagramSocket是UDP Socket,用于发送和接收UDP数据报。我们使用这个类来完成UDP数据传输。

1.1.1 DatagramSocket 构造方法

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)
  • DatagramSocket()操作系统会随机分配一个空闲的端口

  • DatagramSocket(int)port 传入一个端口号(1024~65535),

    DatagramSocket类提供了两个版本,一个带端口(port)一个不带,而带端口的一般用于服务器端,不带端口的一般用于客户端。由于服务端端口的占用情况未知,一般交给操作系统(OS)自动分配,而服务器这边的端口占用情况开发人员一般会比较清楚,所以会手动指定。

1.1.2 DatagramSocket 方法:

方法签名方法说明
void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该法会阻塞等待)
void send(DatagramPacketp)从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()关闭此数据报套接字
  • receive(DatagramPacket p) 这里的p是输出型参数,内部会将数据填入p中
  • send(DatagramPacketp)用来发送数据报,数据要提前存放在DatagramPacket对象中
  • close()使用完后请记得关闭!!!

1.2 DatagramPacket

DatagramPacket是UDP Socket发送和接收的数据报,UDP是面向数据报的。

1.2.1 DatagramPacket构造方法

方法签名方法说明
DatagramPacket(byte[] buf, int length)构造一个DatagramPacket 用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP和端口号
  • DatagramPacket(byte[] buf, int length) 指定byte数组作为缓冲区,length是要存放的长度
  • DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 比上面多路一个offset(偏移量)和address,offset表示从第几个字节开始填充,address表示ip地址和端口号。

1.2.2 DaragramPacket方法

InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
int getPort()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
byte[] getData()获取数据报中的数据
  • InetSddress getAddress() 获取IP地址
  • int getPort() 获取端口
    -byte[] getData() 获取数据报中的数据

    构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创建。

1.2.3InetSocketAddress API

方法签名方法说明
InetSocketAddress(InetAddress addr, int port)创建一个Socket地址,包含IP地址和端口号

    了解了上面这两个类我们就可以在Java中利用UDP来编写一个回显程序。

1.3 UDP回显服务器

1.3.1 框架结构

    首先搭建服务器程序的基本框架,并在构造方法中创建出一个DatagramSocket对象。构造时要传入一个端口号,因为在网络通信中,服务器是被动方,如果端口号为随机,那么此时客户端就不知道服务器的端口号,也就无法进行通信了。

public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}public void start() {}
}

    接着在start中实现具体的服务器代码,首先是一个while(true)循环包含整个方法体,因为大多数服务器7*24小时运行,不断处理客户端发送的请求,返回响应。

1.3.2 读取请求并解析

// receive 方法的参数是一个输出型参数
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
// 如果客户端发来了请求,receive就能顺利读出来请求,如果没有请求就会进入阻塞
socket.receive(requestPacket);
// 将数组中的数据转化为字符串,方便读取
String request = new String(requestPacket.getData(),0,requestPacket.getLength());

1.3.3 根据请求构建响应

 String response = process(request);// .......public String process(String request) {return request;}

1.3.4 响应发回客户端

// 此处DatagramPacket 的参数就不能是空的数组了,因为要将响应的字符串返回去
// send的参数也是DatagramPacket
// 在receive时,requestPacket中已经存放了 客户端的IP地址和端口号
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());
socket.send(responsePacket);

1.3.5 打印日志

System.out.printf("[%s:%d] req: %s;resp : %s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
// 日志格式 - 客户端的IP,客户端的端口号,请求,响应

1.3.6 完整程序

package UDPEchoServer;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {// 创建一个DatagramSocket对象,操作网卡private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {// 服务器端手动分配端口 - 只申请了一个socket对象,一直使用到结束不用close()socket = new DatagramSocket(port);}// 启动服务器public void start() throws IOException {System.out.println("服务器启动!!!");while(true) {// 1.读取请求并解析 => 字节数组(输出型参数)DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);// 当前完成receive后数据是以二进制存储到requestPacket中// 想要显示出这里的请求,还需要将这里的字节数组够造成字符串// getLength() 拿到的是收到的数据的真实长度(字节数)String request = new String(requestPacket.getData(),0,requestPacket.getLength());// 2. 根据请求计算响应(业务)String response = process(request);// 3. 把响应写会客户端// 响应对象DatagramPacket ,构造好响应数据,再通过send发送【指定数据和目的地(无连接)】DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);// 打印日志,把这次交互的详情打印出来System.out.printf("[%s,%d] req=%s, req=%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}public String process(String request) {// 当前是echo server 请求即响应return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(5265);// port range :1023 ~  65535	server.start();}
}

1.4 UDP回显客户端

1.4.1构建框架

    构建客户端的基本框架,相比于服务器,客户端在构造方法处还需要传入服务器的端口号和IP。

public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP = null;private int serverPort = 0;public UdpEchoClient(String serverIP,int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}public void start() {}
}

1.4.2 控制台读取数据构建请求

Scanner scanner = new Scanner(System.in);System.out.print("->");
String request = scanner.next();
// 判断是否要退出
if(request.equals("exit")) {System.out.println("goodbye");break;
}

1.4.3 发送请求

// 构造一个 DatagramPacket 对象 此时该对象的参数要传入客户端的 IP(serverIP) 和 端口(serverPort)
// 此处的IP需要使用getByName()方法
DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIP),serverPort);
socket.send(requestPacket);

1.4.4 接收响应

DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
String response = new String(responsePacket.getData(),0,responsePacket.getLength());

1.4.5 输出响应

System.out.println(response);

1.4.6 完整代码

package UDPEchoServer;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp = "";private int serverPort = 0;public UdpEchoClient(String ip, int port) throws SocketException {// 系统自动分配客户端端口socket = new DatagramSocket();this.serverIp = ip;this.serverPort = port;}public void start() throws IOException {System.out.println("客户端启动!!!");Scanner scanner = new Scanner(System.in);while (true) {// 1. 从控制台读取数据,作为请求System.out.print("-> ");String request = scanner.next();// 2. 把请求够造成DatagramPacket对象DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);// 3. 发送请求socket.send(requestPacket);// 4. 尝试读取响应DatagramPacket responPacket = new DatagramPacket(new byte[4096],4096);socket.receive(responPacket);// 5. 将响应转成字符串打印出来String response = new String(responPacket.getData(),0,responPacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient client = new UdpEchoClient("152.136.59.108",9090);client.start();}
}

2. TCP

2.1 ServerSocket

    ServerSocket 是TCP服务端的API。

2.1.1ServerSocket 构造方法

    ServerSocket 是创建TCP服务端Socket的API

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

2.1.2 ServerSocket 方法

方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端 Socket 对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

2.2 Socket

    Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

2.2.1 Socket 构造方法

方法签名方法说明
Socket(String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

2.2.2 Socket 方法

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

2.3 UDP回显服务器

    由于流程和UDP大差不差,这里介绍一些大概步骤,然后给出所有代码。

  1. 读取请求并解析

  2. 根据请求构造响应

  3. 响应返回客户端

  4. 打印日志

完整代码

package network;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动!");ExecutorService service = Executors.newCachedThreadPool();while (true) {// 通过 accept 方法, 把内核中已经建立好的连接拿到应用程序中.// 建立连接的细节流程都是内核自动完成Socket clientSocket = serverSocket.accept();// 使用线程池.service.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}}// 通过这个方法, 来处理当前的连接.public void processConnection(Socket clientSocket) {// 进入方法, 先打印一个日志, 表示当前有客户端连上了.System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());// 接下来进行数据的交互.try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 使用 try ( ) 方式, 避免后续用完了流对象, 忘记关闭.// 由于客户端发来的数据, 可能是 "多条数据", 针对多条数据, 就循环的处理.while (true) {Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()) {// 连接断开了. 此时循环就应该结束System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort());break;}// 1. 读取请求并解析. 此处就以 next 来作为读取请求的方式. next 的规则是, 读到 "空白符" 就返回.String request = scanner.next();// 2. 根据请求, 计算响应.String response = process(request);// 3. 把响应写回到客户端.//    可以把 String 转成字节数组, 写入到 OutputStream//    也可以使用 PrintWriter 把 OutputStream 包裹一下, 来写入字符串.PrintWriter printWriter = new PrintWriter(outputStream);//    此处的 println 不是打印到控制台了, 而是写入到 outputStream 对应的流对象中, 也就是写入到 clientSocket 里面.//    此处使用 println 带有 \n 也是为了后续 客户端这边 可以使用 scanner.next 来读取数据.printWriter.println(response);//    刷新缓冲区. 如果没有刷新操作, 可能数据仍然是在内存中, 没有被写入网卡.printWriter.flush();// 4. 打印一下这次请求交互过程的内容System.out.printf("[%s:%d] req=%s, resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(),request, response);}} catch (IOException e) {e.printStackTrace();} finally {try {// 在这个地方, 进行 clientSocket 的关闭.// processConnection 就是在处理一个连接. 这个方法执行完毕, 这个连接也就处理完了.clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {// 此处也是写的回显服务器. 响应和请求是一样的.return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

2.4 UDP回显客户端

    同样,这里也是给出流程和完整代码。

  1. 控制台读取数据构建请求

  2. 发送请求

  3. 接收响应

  4. 打印日志

完整代码

package network;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIp, int serverPort) throws IOException {// 需要在创建 Socket 的同时, 和服务器 "建立连接", 此时就得告诉 Socket 服务器在哪里~~// 具体建立连接的细节, 不需要咱们代码手动干预. 是内核自动负责的.// 当我们 new 这个对象的时候, 操作系统内核, 就开始进行 三次握手 具体细节, 完成建立连接的过程了.socket = new Socket(serverIp, serverPort);}public void start() {// tcp 的客户端行为和 udp 的客户端差不多.// 都是:// 3. 从服务器读取响应.// 4. 把响应显示到界面上.Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {PrintWriter writer = new PrintWriter(outputStream);Scanner scannerNetwork = new Scanner(inputStream);while (true) {// 1. 从控制台读取用户输入的内容System.out.print("-> ");String request = scanner.next();// 2. 把字符串作为请求, 发送给服务器//    这里使用 println, 是为了让请求后面带上换行.//    也就是和服务器读取请求, scanner.next 呼应writer.println(request);writer.flush();// 3. 读取服务器返回的响应.String response = scannerNetwork.next();// 4. 在界面上显示内容了.System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);client.start();}
}

3. UDP和TCP的异同

3.1 异

  • UDP 是无连接的,TCP是有连接的
  • UDP 是不可靠传输的,TCP是可靠传输的
  • UDP 是面向数据报的,TCP是面向字节流的

3.2 同

    UDP 和 TCP都是全双工的,什么是全双工?一个信道既可以接收数据又可以发送数据就是全双工的。
在这里插入图片描述

4. 部署至云服务器

4.1 打包

    这里就使用IDE进行打包(jar包)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/06061fa462e845409c659bafaff403f9.png
在这里插入图片描述
    此时就会多出一个out目录,这个目录下artifacts目录下就会有jar包
在这里插入图片描述

4.2 上传

    将程序上传到云服务器上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.3 执行

在这里插入图片描述
    启动服务端程序!!!

java -jar Network.jar

    最后就可以在其他计算机上运行客户端来访问到这个回显程序服务器了。
在这里插入图片描述

4.4 问题总结:

    记得将你使用的端口在云服务器控制台放行,不然可能也访问不了。
    如果没有安装java环境,请执行以下命令安装环境

yum install java

    如果本篇文章对你有帮助,请点赞、评论、转发,你的支持是我创作的动力。

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

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

相关文章

Docker:命令

Docker:命令 1. 创建MySQL的命令解读2. 基础命令3. 案例 查看DockerHub,拉取Nginx镜像,创建并运行Nginx容器4. 命令别名附录 1. 创建MySQL的命令解读 docker run :创建并运行一个容器,-d 是让容器在后台运行--name:给容器起一个名…

使用脚本整合指定文件/文件夹,执行定制化 ESLint 命令

背景 最近面对一个庞大的项目,但是只需要修改某个模块,每次都手搓命令太麻烦了,于是就想着能不能写个脚本来辅助处理这些事情。 解决方案 定制化一键 ESLint,执行文件下载地址: https://github.com/mazeyqian/go-g…

Python 自动化(十六)静态文件处理

准备工作 将不同day下的代码分目录管理,方便后续复习查阅 (testenv) [rootlocalhost projects]# ls day01 day02 (testenv) [rootlocalhost projects]# mkdir day03 (testenv) [rootlocalhost projects]# cd day03 (testenv) [rootlocalhost day03]# django-admi…

基于nodejs+vue啄木鸟便民维修网站设计与实现

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…

element-plus走马灯不显示

问题描述 依赖正确&#xff0c;代码用法正确&#xff0c;但是element-plu走马灯就是不显示&#xff01;&#xff01; <div class"content"><el-carousel height"150px" width"200px"><el-carousel-item v-for"item in 4&qu…

1、Flink基础概念

1、基础知识 &#xff08;1&#xff09;、数据流上的有状态计算 &#xff08;2&#xff09;、框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。 &#xff08;3&#xff09;、事件驱动型应用&#xff0c;有数据流就进行处理&#xff0c;无数据流就不…

1 — NLP 的文本预处理技术

一、说明 在本文中&#xff0c;我们将讨论以下主题&#xff1a;1为什么文本预处理很重要&#xff1f;2 文本预处理技术。这个文对预处理做一个完整化、程序化处理&#xff0c;这对NLP处理项目中有很大参考性。 系列文章的后续&#xff1a; 2、NLP文本预处理技术&#xff1a;词干…

Whisper 从0安装教程 windows

这里写自定义目录标题 Whisper 从0安装教程 windows安装过程安装python3.11安装Anaconda在Anaconda里面安装whisper安装 ffmpeg第一次运行whisper检查GPU 一些弯路 Whisper 从0安装教程 windows 因为需要把语音变成文字稿&#xff0c;问了做语言相关的朋友&#xff0c;决定使用…

【深度学习基础】从R-CNN到Fast R-CNN,再到MaskR-CNN,发展历程讲清楚!

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

代码随想录第五十七天|● 392.判断子序列 ● 115.不同的子序列

392.判断子序列 题目&#xff1a; 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是&qu…

Python之循环语句

循环普遍存在于日常生活中&#xff0c;同样&#xff0c;在程序中&#xff0c;循环功能也是至关重要的基础功能。 循环在程序中同判断一样&#xff0c;也是广泛存在的&#xff0c;是非常多功能实现的基础 while循环的基础语法 生活中的循环 程序中的循环 只要条件满足 会无限循…

【EI会议征稿】第四届生物信息学与智能计算国际学术研讨会(BIC 2024)

第四届生物信息学与智能计算国际学术研讨会&#xff08;BIC 2024&#xff09; 2024 4th International Conference on Bioinformatics and Intelligent Computing 2024年第四届生物信息学与智能计算国际学术研讨会 &#xff08;BIC 2024&#xff09;将定于2024年1月26-28日在…

循环神经网络 - RNN

循环神经网络&#xff08;Rerrent Neural Network,RNN&#xff09;是神经网络的一种&#xff0c;类似的还有深度神经网络&#xff08;DNN&#xff09;、卷积神经网路(CNN)、生成对抗网络&#xff08;GAN)等。**RNN对具有时序特性的数据非常有成效&#xff0c;他能挖掘数据中的时…

OSPF复习(2)

目录 一、LSA的头部 二、6种类型的LSA&#xff08;课堂演示&#xff09; 1、type1-LSA&#xff1a;----重要且复杂 2、type2-LSA&#xff1a; 3、type3-LSA&#xff1a; 4、type4-LSA&#xff1a; 5、type5-LSA&#xff1a; 6、type7-LSA&#xff1a; 三、OSPF的网络类…

【OpenCV实现图像:用Python生成图像特效,报错ValueError: too many values to unpack (expected 3)】

文章目录 概要读入图像改变单个通道黑白特效颜色反转将图像拆分成四个子部分 概要 Python是一种功能强大的编程语言&#xff0c;也是图像处理领域中常用的工具之一。通过使用Python的图像处理库&#xff08;例如Pillow、OpenCV等&#xff09;&#xff0c;开发者可以实现各种各…

Emscripten + CMakeLists.txt 将 C++ 项目编译成 WebAssembly(.wasm)/js,并编译 Html 测试

背景&#xff1a;Web 端需要使用已有的 C 库&#xff08;使用 CMake 编译&#xff09;&#xff0c;需要将 C 项目编译成 WebAssembly(.wasm) 供 js 调用。 上篇文章《Mac 上安装 Emscripten》 已讲解如何安装配置 Emscripten 环境。 本篇文章主要讲解如何将基于 CMakeLists 配…

SpringCloud(五) Eureka与Nacos的区别

SpringCloud(二) Eureka注册中心的使用-CSDN博客 SpringCloud(四) Nacos注册中心-CSDN博客 在这两篇博文中我们详细讲解了Eureka和Nacos分别作为微服务的注册中心的使用方法和注意事项,但是两者之间也有一些区别. 一, Nacos实例分类 Nacos实例分为两种类型: 临时实例:如果实例…

【QT】仿函数

函数调用运算符 () 也可以重载由于重载后使用的方式非常像函数的调用&#xff0c;因此称为仿函数仿函数没有固定写法&#xff0c;非常灵活 示例&#xff1a; #include <iostream> #include <string> using namespace std;class MyPrint { public://重载的运算符是…

【数据结构与算法】排序二叉树的创建节点的添加和删除(附代码实现与代码讲解)

首先来了解下排序二叉树的基本概念 排序二叉树&#xff1a;任意一个根节点&#xff0c;比他的左子树中的任意节点都大&#xff0c;比他的右子树中的任意节点都小 比如下面的这个树就是排序二叉树 OK&#xff0c;在了解了这个基本概念之后&#xff0c;就可以去看下面的代码了 …

【Linux】关于Nginx的详细使用,部署项目

前言&#xff1a; 今天小编给大家带来的是关于Nginx的详细使用&#xff0c;部署项目&#xff0c;希望可以给正在学习&#xff0c;工作的你带来有效的帮助&#xff01; 一&#xff0c;Nginx简介 Nginx是一个高性能的开源Web服务器和反向代理服务器。它最初由Igor Sysoev在2004年…