网络编程

    • 1.1软件结构
    • 1.2 网络通信协议
    • 1.3 协议分类
    • 1.4网络编程三要素
      • 协议
      • IP地址
      • 端口号
  • TCP通信程序
    • 2.1 概述
    • 2.2 Socket类
      • 构造方法
      • 成员方法
    • 2.3 ServerSocket类
      • 构造方法
      • 成员方法
    • 2.4 简单的TCP网络程序
      • TCP通信分析图解
      • 客户端向服务器发送数据
  • 综合案例
    • 3.1 文件上传案例
      • 文件上传优化分析
        • 优化实现
      • 信息回写分析图解
        • 回写实现

1.1软件结构

  • C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件。

  • B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。

    两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的协议下,实现两台计算机的通信的程序。

1.2 网络通信协议

  • **网络通信协议通:**过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。

  • TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

    上图中,TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。

  • 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。

  • 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。

  • 运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。

  • 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。

1.3 协议分类

通信的协议还是比较复杂的,java.net 包中包含的类和接口,它们提供底层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
java.net 包中提供了两种常见的网络协议的支持:

  • UDP:用户数据报协议(User Datagram Protocol)。UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。

特点:数据被限制在64kb以内,超出这个范围就不能发送了。

数据报(Datagram):网络传输的基本单位
TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。

在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。
三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

  • 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
  • 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
  • 第三次握手,客户端再次向服务器端发送确认信息,确认连接。整个交互过程如下图所示。

完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。

1.4网络编程三要素

协议

  • 协议:计算机网络通信必须遵守的规则

IP地址

  • IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。

IP地址分类

  • IPv4:是一个32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。

  • IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。

    为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。

常用命令

  • 查看本机IP地址,在控制台输入:
ipconfig
  • 检查网络是否连通,在控制台输入:
ping 空格 IP地址
ping 220.181.57.216

特殊的IP地址

  • 本机IP地址:127.0.0.1localhost

端口号

网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?

如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。

  • **端口号:用两个字节表示的整数,它的取值范围是065535**。其中,01023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。

TCP通信程序

2.1 概述

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。

两端通信时步骤:

  1. 服务端程序,需要事先启动,等待客户端的连接。
  2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

在Java中,提供了两个类用于实现TCP通信程序:

  1. 客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
  2. 服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

2.2 Socket类

Socket 类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。

构造方法

  • public Socket(String host, int port) :创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址。

    小贴士:回送地址(127.x.x.x) 是本机回送地址(Loopback Address),主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不进行任何网络传输。

构造举例,代码如下:

Socket client = new Socket("127.0.0.1", 6666);

成员方法

  • public InputStream getInputStream() : 返回此套接字的输入流。

    • 如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。
    • 关闭生成的InputStream也将关闭相关的Socket。
  • public OutputStream getOutputStream() : 返回此套接字的输出流。

    • 如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。
    • 关闭生成的OutputStream也将关闭相关的Socket。
  • public void close() :关闭此套接字。

    • 一旦一个socket被关闭,它不可再使用。
    • 关闭此socket也将关闭相关的InputStream和OutputStream 。
  • public void shutdownOutput() : 禁用此套接字的输出流。

    • 任何先前写出的数据将被发送,随后终止输出流。

    2.3 ServerSocket类

ServerSocket类:这个类实现了服务器套接字,该对象等待通过网络的请求。

构造方法

  • public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。

构造举例,代码如下:

ServerSocket server = new ServerSocket(6666);

成员方法

  • public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。

2.4 简单的TCP网络程序

TCP通信分析图解

  1. 【服务端】启动,创建ServerSocket对象,等待连接。
  2. 【客户端】启动,创建Socket对象,请求连接。
  3. 【服务端】接收连接,调用accept方法,并返回一个Socket对象。
  4. 【客户端】Socket对象,获取OutputStream,向服务端写出数据。
  5. 【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。

到此,客户端向服务端发送数据成功。

自此,服务端向客户端回写数据。

  1. 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
  2. 【客户端】Scoket对象,获取InputStream,解析回写数据。
  3. 【客户端】释放资源,断开连接。

客户端向服务器发送数据

服务端实现:

/**TCP协议服务端 : ServerSocketSocket accept() 侦听链接的客户端*/
public class NewTcpServer {public static List<MyChannel> all;//创建集合ArrayList;用于存储接收客户对象public static void main(String[] args) throws IOException {//实例化服务端ServerSocket,并且监听指定端口号ServerSocket server = new ServerSocket(9999);all = new ArrayList<>();int count=0;while (true){//服务端可以监听到连接的客户端是谁;;Socket accept()方法;Socket client = server.accept();System.out.println("一个socket连接...");//接收客户端的数据/发送信息给客户端count++;MyChannel channel = new MyChannel(count,client,all);new Thread(channel).start();all.add(channel);}}
}

服务端 线程程序类

public class MyChannel implements Runnable {//用于接收客户端套接字private Socket accept;//服务器读取客户端数据流  DataInputStreamprivate DataInputStream dis;//控制台输出private BufferedReader console;//服务器向客户端输出数据private DataOutputStream dos;//可执行标识private boolean isRunning = true;private int id;private List<MyChannel> all;public MyChannel(int count, Socket accept, List<MyChannel> all) {id = count;this.all = all;this.accept = accept;try {//服务器读取客户端消息dis = new DataInputStream(accept.getInputStream());dos = new DataOutputStream(accept.getOutputStream());//控制台写信息console = new BufferedReader(new InputStreamReader(System.in));} catch (IOException e) {IOUtilss.closeAll(dis, dos, accept, console);isRunning = false;}}@Overridepublic void run() {//接收客户端的数据   Receive()方法while (isRunning) {String msg = receive();if (msg.contains("@")){
//                Chat(msg);}else {allChat(msg);}System.out.println(msg);
//            String sfc = getStrFromConsole();}}private void Chat(String msg) {String s = msg.replace("@", "");}private void allChat(String msg) {for (MyChannel myChannel : all) {if (myChannel == this) {} else {try {myChannel.dos.writeUTF(msg);} catch (IOException e) {e.printStackTrace();}}}}//服务器接收客户端消息public String receive() {String data = "";try {String s = dis.readUTF();if (!s.equals("")) {data = s;}} catch (IOException e) {IOUtilss.closeAll(dis);isRunning = false;}return data;}//从控制台读出信息public String getStrFromConsole() {try {String s = console.readLine();if (!s.equals("")) {return s;}} catch (IOException e) {e.printStackTrace();}return "";}//服务器向客户端发送消息public void send(String msg) {try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {isRunning = false;//IOUtilss.closeAll(dos);}}
}

客户端实现:

public class NewTcpClient {public static void main(String[] args) throws IOException {System.out.println("=====客户端====");//新建Scoket//1、指定ip+端口号;建立连接Socket socket = new Socket("127.0.0.1",9999);//2、创建两条线程:保证客户端发送&&接收消息互不干扰//一个发送消息的类对象Send(socket);含一个参数的构造方法;用于传参建立连接//一个接收消息的类对象Receive(socket);含一个参数的构造方法;用于传参建立连接new Thread( new Send(socket)).start();new Thread(new Receive(socket)).start();}
}

发送线程实现类

//客户端发送任务
//1、创建客户连接、
// 2、客户发送消息的dataoutputStream流
// 3、从键盘获取消息的BufferReader流
//run方法中:得到控制台消息getStrFormConsole(),发送消息send()
public class Send implements Runnable{//用于接收客户端套接字private Socket client;              //客户端连接private DataOutputStream dos;       //客户端发送信息;dataOutputStream流实现private BufferedReader console;     //控制台接收键盘信息;BufferedReader实现//可执行标记private boolean isRunning = true;public Send(Socket client) {this.client = client;try {//借助转换流,在控制台输入数据console = new BufferedReader(new InputStreamReader(System.in));dos = new DataOutputStream(client.getOutputStream());} catch (IOException e) {//如果出现异常,客户端挺会发送消息,流关闭IOUtilss.closeAll(console,client,dos);isRunning=false;}}@Overridepublic void run() {while (isRunning){//获取键盘输入的数据//传一个获取数据的方法String strFormConsole = getStrFormConsole();//判断(如果数据不为空,则输出数据;)if(!strFormConsole.equals("")){send(strFormConsole);}}}//从控制台获取消息private String getStrFormConsole(){try {return console.readLine();} catch (IOException e) {e.printStackTrace();}return "";}//将获取到的消息发送给服务器public void send(String msg){try {dos.writeUTF(msg);dos.flush();} catch (IOException e) {e.printStackTrace();isRunning = false;}}
}

客户端接收类实现;

/*** 客户端接收任务* 1、建立Socket连接;* 2、创建读入服务器数据的流DataInputStream* 3、设计一个表示,判断读入数据是否停止* 4、run方法中接收服务器传来的数据receive()方法*/public class Receive implements Runnable{private Socket client;private DataInputStream dis;private boolean isRunning = true;public Receive(Socket client) {this.client = client;try {//创建输入流,连接客户端dis = new DataInputStream(client.getInputStream());} catch (IOException e) {//如果出现异常,关闭流、结束线程IOUtilss.closeAll(dis);isRunning = false;}}@Overridepublic void run() {while (isRunning){//接收服务器传来的消息String msg = receive();//判断:如果服务器传来的消息不是空的,输出消息if(!msg.equals("")){System.out.println(msg);}}}//客户端从服务器读出数据public String  receive(){String msg = "";try {msg = dis.readUTF();} catch (IOException e) {IOUtilss.closeAll(dis,client);isRunning = false;}return msg;}
}

综合案例

3.1 文件上传案例

  1. 【客户端】输入流,从硬盘读取文件数据到程序中。
  2. 【客户端】输出流,写出文件数据到服务端。
  3. 【服务端】输入流,读取文件数据到服务端程序。
  4. 【服务端】输出流,写出文件数据到服务器硬盘中。
    服务端实现:
public class FileUpload_Server {public static void main(String[] args) throws IOException {System.out.println("服务器 启动.....  ");// 1. 创建服务端ServerSocketServerSocket serverSocket = new ServerSocket(6666);// 2. 建立连接 Socket accept = serverSocket.accept();// 3. 创建流对象// 3.1 获取输入流,读取文件数据BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());// 3.2 创建输出流,保存到本地 .BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));// 4. 读写数据byte[] b = new byte[1024 * 8];int len;while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);}//5. 关闭 资源bos.close();bis.close();accept.close();System.out.println("文件上传已保存");}
}

客户端实现:

public class FileUPload_Client {public static void main(String[] args) throws IOException {// 1.创建流对象// 1.1 创建输入流,读取本地文件  BufferedInputStream bis  = new BufferedInputStream(new FileInputStream("test.jpg"));// 1.2 创建输出流,写到服务端 Socket socket = new Socket("localhost", 6666);BufferedOutputStream   bos   = new BufferedOutputStream(socket.getOutputStream());//2.写出数据. byte[] b  = new byte[1024 * 8 ];int len ; while (( len  = bis.read(b))!=-1) {bos.write(b, 0, len);bos.flush();}System.out.println("文件发送完毕");// 3.释放资源bos.close(); socket.close();bis.close(); System.out.println("文件上传完毕 ");}
}

文件上传优化分析

  1. 文件名称写死的问题

    服务端,保存文件的名称如果写死,那么最终导致服务器硬盘,只会保留一个文件,建议使用系统时间优化,保证文件名称唯一,代码如下:

FileOutputStream fis = new FileOutputStream(System.currentTimeMillis()+".jpg") // 文件名称
BufferedOutputStream bos = new BufferedOutputStream(fis);
  1. 循环接收的问题

    服务端,指保存一个文件就关闭了,之后的用户无法再上传,这是不符合实际的,使用循环改进,可以不断的接收不同用户的文件,代码如下:

// 每次接收新的连接,创建一个Socket
while(true){Socket accept = serverSocket.accept();......
}
  1. 效率问题

    服务端,在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化,代码如下:

while(true){Socket accept = serverSocket.accept();// accept 交给子线程处理.new Thread(() -> {......InputStream bis = accept.getInputStream();......}).start();
}

优化实现

public class FileUpload_Server {public static void main(String[] args) throws IOException {System.out.println("服务器 启动.....  ");// 1. 创建服务端ServerSocketServerSocket serverSocket = new ServerSocket(6666);// 2. 循环接收,建立连接while (true) {Socket accept = serverSocket.accept();/* 3. socket对象交给子线程处理,进行读写操作Runnable接口中,只有一个run方法,使用lambda表达式简化格式*/new Thread(() -> {try (//3.1 获取输入流对象BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());//3.2 创建输出流对象, 保存到本地 .FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");BufferedOutputStream bos = new BufferedOutputStream(fis);) {// 3.3 读写数据byte[] b = new byte[1024 * 8];int len;while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);}//4. 关闭 资源bos.close();bis.close();accept.close();System.out.println("文件上传已保存");} catch (IOException e) {e.printStackTrace();}}).start();}}
}

信息回写分析图解

前四步与基本文件上传一致.

  1. 【服务端】获取输出流,回写数据。
  2. 【客户端】获取输入流,解析回写数据。

回写实现

public class FileUpload_Server {public static void main(String[] args) throws IOException {System.out.println("服务器 启动.....  ");// 1. 创建服务端ServerSocketServerSocket serverSocket = new ServerSocket(6666);// 2. 循环接收,建立连接while (true) {Socket accept = serverSocket.accept();/*3. socket对象交给子线程处理,进行读写操作Runnable接口中,只有一个run方法,使用lambda表达式简化格式*/new Thread(() -> {try (//3.1 获取输入流对象BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());//3.2 创建输出流对象, 保存到本地 .FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");BufferedOutputStream bos = new BufferedOutputStream(fis);) {// 3.3 读写数据byte[] b = new byte[1024 * 8];int len;while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);}// 4.=======信息回写===========================System.out.println("back ........");OutputStream out = accept.getOutputStream();out.write("上传成功".getBytes());out.close();//================================//5. 关闭 资源bos.close();bis.close();accept.close();System.out.println("文件上传已保存");} catch (IOException e) {e.printStackTrace();}}).start();}}
}

客户端实现:

public class FileUpload_Client {public static void main(String[] args) throws IOException {// 1.创建流对象// 1.1 创建输入流,读取本地文件BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));// 1.2 创建输出流,写到服务端Socket socket = new Socket("localhost", 6666);BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());//2.写出数据.byte[] b  = new byte[1024 * 8 ];int len ;while (( len  = bis.read(b))!=-1) {bos.write(b, 0, len);}// 关闭输出流,通知服务端,写出数据完毕socket.shutdownOutput();System.out.println("文件发送完毕");// 3. =====解析回写============InputStream in = socket.getInputStream();byte[] back = new byte[20];in.read(back);System.out.println(new String(back));in.close();// ============================// 4.释放资源socket.close();bis.close();}
}

【Java——网络编程基础之客户端服务器连接】相关推荐

  1. 迈入JavaWeb第一步,Java网络编程基础,TCP网络编程URL网络编程等

    文章目录 网络编程概述 网络通信要素 要素一IP和端口号 要素二网络协议 TCP网络编程 UDP网络编程 URL网络编程 Java网络编程基础 网络编程概述 Java是Internet上的语言,它从语 ...

  2. Java网络编程和NIO详解开篇:Java网络编程基础

    老曹眼中的网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为我们拥有网络.网络是一个神奇的东西,它改变了你和我的 ...

  3. Java 网络编程基础知识

    Java 网络编程基础知识 基础概念 计算机网络的基本概念 ​ 网络:多台计算机使用网络设备互联在一起,计算机之间可以进行通信,这样就组成了一个计算机网络. ​ 网络设备:集线器(HUB),路由器,交 ...

  4. Java网络编程基础_Java网络编程基础篇

    一.前言 网络通讯在系统交互中是必不可少的一部分,无论是面试还是工作中都是绕不过去的一部分,本节我们来谈谈Java网络编程中的一些知识,本chat内容如下: 网络通讯基础知识,剖析网络通讯的本质和需要 ...

  5. Java网络编程基础学习

    网络编程 1. 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备**,**通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计 ...

  6. 一、Java网络编程基础

    1.计算机网络体系结构 1.1 OSI七层模型 开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联 ...

  7. JAVA 网络编程基础

    一,前言 了解计算机网络的概述,掌握Sokcet类编程,ServerSocket类,Socket类的构造方法和常用方法 二,计算机网咯 1.概述 计算机网络计算机们组成的网络,同一个网络中,计算机可以 ...

  8. java网络编程Socket实现客户端向服务端发送信息

    (可按目录按需阅读,我一般会整理的比较细) 前置知识 java IO Socket 什么是socket?socket字面意思其实就是一个插口或者套接字,包含了源ip地址.源端口.目的ip地址和源端口. ...

  9. Java网络编程基础(七)— RMI分布式网络编程

    Java RMI指的是远程方法调用(Remote Method Invocation).它是一种机制,能够让在某个机器上的Java程序调用另一个机器上的Java程序的方法,用此方法调用的任何对象必须实 ...

最新文章

  1. 还在做Excel分析师?HR:对不起,我们还要求会Python!
  2. 本轮股市行情性质的分析
  3. 学习笔记(四)——JavaScript(一)
  4. 【Lucene4.8教程之三】搜索
  5. 在 Eclipse 3.5中在线安装SVN插件
  6. dptcpp 题目 2352: [信息学奥赛一本通-T1440]数的划分-dp
  7. 谷歌开源的 GAN 库--TFGAN
  8. Laravel 开发扩展包基本流程
  9. Ubuntu18.04下安装OpenCV依赖包出现ibjasper-dev无法安装的问题
  10. Atitit 信息检索 v3 t55.docx Atitit 现代信息检索 目录 1.1. 信息检索(索引 索引 结构化文本 1 1.2. Atitit 重要章节 1 1.3. 息检索建模 1 1.
  11. 小米路由器mini R1C R1CM openwrt源 换源
  12. 全球及中国石油市场十四五发展走势及竞争格局动态分析报告2021年版
  13. SAP 会计科目表并存时会计科目映射
  14. 单片机24秒倒计时c语言,基于51单片机的篮球24秒倒计时器
  15. php截断,php include 路径截断漏洞的利用
  16. ElasticSearch---------------------step3,安装Kibana
  17. Charles 的简单使用
  18. DC学习-前言及第一章
  19. 【人工智能】院士谈新一代人工智能五大智能方向
  20. 证书透明度(Certificate Transparency)

热门文章

  1. 一些名词或者术语(不断补充中……)
  2. Junit 入门级使用教程
  3. 大模型商业的搅局者?除了谷歌和微软,你可能忘记了它!
  4. (四)本地镜像发布到阿里云将阿里云上的镜像下载到本地
  5. python返回函数值并退出函数_python3函数中如何退出程序
  6. 制作Linux嵌入式系统开机LOGO(图片)
  7. java ----数据结构和算法
  8. EggBorn.js Showcase: Watch Articles
  9. 俞敏洪:我让女儿主动学习的秘密
  10. VR全景看房线上3D住宅商品房鉴赏