javaEE -8(9000字详解网络编程)

一:网络编程基础

1.1 网络资源

所谓的网络资源,其实就是在网络中可以获取的各种数据资源,而所有的网络资源,都是通过网络编程来进行数据传输的。

在这里插入图片描述
用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源,与本地打开视频文件类似,只是视频文件这个资源的来源是网络。
在这里插入图片描述
那么我们怎么将这些网络资源在不同的设备上进行传输呢?答案是网络编程

1.2 网络编程

网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。
在这里插入图片描述
当然,我们只要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。

特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程。

但是,我们一定要明确,我们的目的是提供网络上不同主机,基于网络来传输数据资源:

  • 进程A:编程来获取网络资源
  • 进程B:编程来提供网络资源

1.3网络编程中的基本概念

1.3.1 发送端和接收端

在一次网络数据传输时:

  • 发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。
  • 接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。
  • 收发端:发送端和接收端两端,也简称为收发端。

注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

在这里插入图片描述

1.3.2 请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输:

  • 第一次:请求数据的发送
  • 第二次:响应数据的发送。

好比在快餐店点一份炒饭:先要发起请求:点一份炒饭,再有快餐店提供的对应响应:提供一份炒饭

在这里插入图片描述

1.3.3 客户端和服务端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。

客户端:获取服务的一方进程,称为客户端。

对于服务来说,一般是提供:

  • 客户端获取服务资源
    在这里插入图片描述
  • 客户端保存资源在服务端

在这里插入图片描述

1.3.4 常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:

  1. 客户端先发送请求到服务端
  2. 服务端根据请求数据,执行相应的业务处理
  3. 服务端返回响应:发送业务处理结果
  4. 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

在这里插入图片描述

二:Socket套接字

因为应用层获得数据需要通过传输层传输,所以我们要通过应用层调用传输层,而传输层也为应用层提供了一个api,统称为 socket api,这个api有两组,一组是基于UDP的api,一组是基于TCP的api,TCP和UDP的差别很大,所以这两组api的差别也很大。

Socket套接字是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。

Socket套接字主要针对传输层协议划分为如下三类:

  1. 流套接字:使用传输层TCP协议
  2. 数据报套接字:使用传输层UDP协议
  3. 原始套接字

TCP,即Transmission Control Protocol(传输控制协议),传输层协议,TCP的特点是:有连接,可靠传输,面向字节流,全双工

UDP,即User Datagram Protocol(用户数据报协议),传输层协议,UDP的特点是:无连接,不可靠传输,面向数据报,全双工

原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

TCP比UDP复杂,因为TCP要保证可靠性,同时又尽可能的提高性能。

因为TCP的机制,不管TCP怎么提高效率,TCP还是不如UDP的

2.1 TCP和UDP特点解析

  1. 有连接 vs 无连接:

有连接是指在数据传输之前,发送方与接收方需要先建立一个可靠的通信链路,以确保双方能够互相通信。在传输过程中,双方需要维护一定的状态信息。而无连接则是指在数据传输之前,发送方和接收方之间不需要建立可靠的通信链路。每个数据包都是独立传输的,不关心之前或之后的数据包。无连接的方式通常适用于对实时性要求较高且传输信息量相对较小的场景。

  1. 可靠传输 vs 不可靠传输:

可靠传输是指数据在传输过程中会被发送方和接收方进行确认,并进行丢失、错误、重复等错误处理,确保数据的完整性和正确性。发送方会等待接收方的确认信息,如果没有得到确认,会重新发送数据。不可靠传输则是指数据在传输过程中不会进行确认,不保证数据的完整性和正确性。这种方式通常用于对实时性要求较高且传输量较大,对数据完整性要求低的场景。

  1. 面向字节流 vs 面向数据报:

面向字节流是指数据在传输过程中被看作是一连串的无结构的字节流,发送方按照字节流进行传输,接收方按照相同的字节流进行接收,不考虑数据的边界或分段。面向字节流适用于传输大文件或需要流式处理的场景。面向数据报则是指数据在传输过程中被分割成数据报的形式进行传输,每个数据报都包含了数据的完整信息,接收方根据数据报的边界进行接收和处理。面向数据报适用于传输小数据量且对数据完整性要求较高的场景。

  1. 全双工 vs 半双工:

全双工是指发送方和接收方能够同时进行数据的发送和接收,可以进行双向通信,彼此不会干扰对方。发送方和接收方之间的通信是完全独立的。全双工通信方式在网络中应用广泛,例如,在电话通信中,发送方和接收方可以同时说话和倾听。半双工则是指发送方和接收方不能同时进行数据的发送和接收,每个时刻只能进行单向通信。发送方和接收方之间的通信是互斥的。半双工通信方式在网络中的应用较少,例如,在对讲机通信中,一个人说话时,另一个人只能倾听。

2.2 在java中如何一次发送及接收UDP数据报

对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报。

java中使用UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用DatagramPacket 作为发送或接收的UDP数据报。对于一次发送及接收UDP数据报的流程如下:
在这里插入图片描述
以上只是一次发送端的UDP数据报发送,及接收端的数据报接收,并没有返回的数据。也就是只有请求,没有响应。对于一个服务端来说,重要的是提供多个客户端的请求处理及响应,流程如下:

在这里插入图片描述

2.3 Socket编程注意事项

在这里插入图片描述

在这里插入图片描述

  1. 客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但真实的场景,一般都是不同主机。
  2. 注意目的IP和目的端口号,标识了一次数据传输时要发送数据的终点主机和进程
  3. Socket编程我们是使用流套接字和数据报套接字,基于传输层的TCP或UDP协议,但应用层协议,也需要考虑,这块我们在后续来说明如何设计应用层协议。

关于端口被占用的问题:如果一个进程A已经绑定了一个端口,再启动一个进程B绑定该端口,就会报错,这种情况也叫端口被占用。对于java进程来说,端口被占用的常见报错信息如下:

在这里插入图片描述

此时需要检查进程B绑定的是哪个端口,再查看该端口被哪个进程占用。以下为通过端口号查进程的方式:

  • 在cmd输入 netstat -ano | findstr 端口号 ,则可以显示对应进程的pid。如以下命令显示了8888进程的pid
    在这里插入图片描述
  • 在任务管理器中,通过pid查找进程
    在这里插入图片描述
    解决端口被占用的问题:
  • 如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B
  • 如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。

三:UDP数据报套接字编程

3.1 DatagramSocket API

DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。

DatagramSocket 构造方法:

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口

DatagramSocket 方法:

方法签名方法说明
void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p)从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

3.2 DatagramPacket API

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

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 方法:

方法签名方法说明
InetAddress.getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址
InetAddress.getPort()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号
DatagramPacket.getData()获取数据报中的数据

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

3.3 InetSocketAddress API

InetSocketAddress ( SocketAddress 的子类 )构造方法:

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

3.4 案例演示

一发一收(无响应)

3.4.1 UDP服务端

package org.example.udp.demo1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
public class UdpServer {//服务器socket要绑定固定的端口private static final int PORT = 8888;public static void main(String[] args) throws IOException {// 1.创建服务端DatagramSocket,指定端口,可以发送及接收UDP数据报DatagramSocket socket = new DatagramSocket(PORT);//不停的接收客户端udp数据报while (true){// 2.创建数据报,用于接收客户端发送的数据byte[] bytes = new byte[1024];//1m=1024kb, 1kb=1024byte, UDP最多
64k(包含UDP首部8byte)DatagramPacket packet = new DatagramPacket(bytes, bytes.length);System.out.println("------------------------------------------------
---");System.out.println("等待接收UDP数据报...");// 3.等待接收客户端发送的UDP数据报,该方法在接收到数据报之前会一直阻塞,接收到数据报以后,DatagramPacket对象,包含数据(bytes)和客户端ip、端口号socket.receive(packet);System.out.printf("客户端IP:%s%n",packet.getAddress().getHostAddress());System.out.printf("客户端端口号:%s%n", packet.getPort());System.out.printf("客户端发送的原生数据为:%s%n", Arrays.toString(packet.getData()));System.out.printf("客户端发送的文本数据为:%s%n", new String(packet.getData()));}}
}

运行后,服务端就启动了,控制台输出如下:


等待接收UDP数据报…

可以看出,此时代码是阻塞等待在 socket.receive(packet) 代码行,直到接收到一个UDP数据报。

3.4.2 UDP客户端

package org.example.udp.demo1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
public class UdpClient {// 服务端socket地址,包含域名或IP,及端口号private static final SocketAddress ADDRESS = new
InetSocketAddress("localhost", 8888);public static void main(String[] args) throws IOException {// 4.创建客户端DatagramSocket,开启随机端口就行,可以发送及接收UDP数据报DatagramSocket socket = new DatagramSocket();// 5-1.准备要发送的数据byte[] bytes = "hello world!".getBytes();// 5-2.组装要发送的UDP数据报,包含数据,及发送的服务端信息(服务器IP+端口号)DatagramPacket packet = new DatagramPacket(bytes, bytes.length,ADDRESS);// 6.发送UDP数据报socket.send(packet);}
}

客户端启动后会发送一个"hello world!" 的字符串到服务端,在服务端接收后,控制台输出内容如下:


等待接收UDP数据报…
客户端IP:127.0.0.1
客户端端口号:57910
客户端发送的原生数据为:[104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33,
0, 0, 0, …此处省略很多0]
客户端发送的文本数据为:hello world!


等待接收UDP数据报…

从以上可以看出,发送的UDP数据报(假设发送的数据字节数组长度为M),在接收到以后(假设接收的数据字节数组长度为N):

  1. 如果N>M,则接收的byte[]字节数组中会有很多初始化byte[]的初始值0,转换为字符串就是空白字符;
  2. 如果N<M,则会发生数据部分丢失(可以自己尝试,把接收的字节数组长度指定为比发送的字节数组长度更短)。

要解决以上问题,就需要发送端和接收端双方约定好一致的协议,如规定好结束的标识或整个数据的长度。

四:TCP流套接字编程

4.1 ServerSocket API

ServerSocket 是创建TCP服务端Socket的API。

ServerSocket 构造方法:

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

ServerSocket 方法:

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

4.2 Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。

不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

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

Socket 方法:

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

4.3 TCP中的长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

  • 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
  • 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

对比以上长短连接,两者区别如下:

  1. 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。

  2. 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。

  3. 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

扩展了解:
基于BIO(同步阻塞IO)的长连接会一直占用系统资源。对于并发要求很高的服务端系统来说,这样的消耗是不能承受的。

由于每个连接都需要不停的阻塞等待接收数据,所以每个连接都会在一个线程中运行。

一次阻塞等待对应着一次请求、响应,不停处理也就是长连接的特性:一直不关闭连接,不停的处理请求。

实际应用时,服务端一般是基于NIO(即同步非阻塞IO)来实现长连接,性能可以极大的提升。

4.4 案例演示

一发一收(短连接)

以下为一个客户端一次数据发送,和服务端多次数据接收(一次发送一次接收,可以接收多次),即只有客户端请求,但没有服务端响应的示例:

4.4.1 TCP服务端

package org.example.tcp.demo1;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {//服务器socket要绑定固定的端口private static final int PORT = 8888;public static void main(String[] args) throws IOException {// 1.创建一个服务端ServerSocket,用于收发TCP报文ServerSocket server = new ServerSocket(PORT);// 不停的等待客户端连接while(true) {System.out.println("---------------------------------------------------");System.out.println("等待客户端建立TCP连接...");// 2.等待客户端连接,注意该方法为阻塞方法Socket client = server.accept();System.out.printf("客户端IP:%s%n",client.getInetAddress().getHostAddress());System.out.printf("客户端端口号:%s%n", client.getPort());// 5.接收客户端的数据,需要从客户端Socket中的输入流获取System.out.println("接收到客户端请求:");InputStream is = client.getInputStream();// 为了方便获取字符串内容,可以将以上字节流包装为字符流BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));String line;// 一直读取到流结束:TCP是基于流的数据传输,一定要客户端关闭Socket输出流才表示服务端接收IO输入流结束while ((line = br.readLine()) != null) {System.out.println(line);}// 6.双方关闭连接:服务端是关闭客户端socket连接client.close();}}
}

运行后,服务端就启动了,控制台输出如下:


等待客户端建立TCP连接…

可以看出,此时代码是阻塞等待在 server.accept() 代码行,直到有新的客户端申请建立连接。

4.4.2 TCP客户端

package org.example.tcp.demo1;
import java.io.*;
import java.net.Socket;
public class TcpClient {//服务端IP或域名private static final String SERVER_HOST = "localhost";//服务端Socket进程的端口号private static final int SERVER_PORT = 8888;public static void main(String[] args) throws IOException {// 3.创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接Socket client = new Socket(SERVER_HOST, SERVER_PORT);// 4.发送TCP数据,是通过socket中的输出流进行发送OutputStream os = client.getOutputStream();// 为了方便输出字符串作为发送的内容,可以将以上字节流包装为字符流PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));// 4-1.发送数据:pw.println("hello world!");// 4-2.有缓冲区的IO操作,真正传输数据,需要刷新缓冲区pw.flush();// 7.双方关闭连接:客户端关闭socket连接client.close();}
}

客户端启动后会发送一个"hello world!" 的字符串到服务端,在服务端接收后,控制台输出内容如下:


等待客户端建立TCP连接…
客户端IP:127.0.0.1
客户端端口号:51118
接收到客户端请求:
hello world!


等待客户端建立TCP连接…

以上客户端与服务端建立的为短连接,每次客户端发送了TCP报文,及服务端接收了TCP报文后,双方都会关闭连接。

五:再谈协议

以上我们实现的UDP和TCP数据传输,除了UDP和TCP协议外,程序还存在应用层自定义协议,可以想想分别都是什么样的协议格式。

对于客户端及服务端应用程序来说,请求和响应,需要约定一致的数据格式:

  • 客户端发送请求和服务端解析请求要使用相同的数据格式。
  • 服务端返回响应和客户端解析响应也要使用相同的数据格式。
  • 请求格式和响应格式可以相同,也可以不同。
  • 约定相同的数据格式,主要目的是为了让接收端在解析的时候明确如何解析数据中的各个字段。
  • 可以使用知名协议(广泛使用的协议格式),如果想自己约定数据格式,就属于自定义协议。

5.1 封装/分用 vs 序列化/反序列化

一般来说,在网络数据传输中,发送端应用程序,发送数据时的数据转换(如java一般就是将对象转换为某种协议格式),即对发送数据时的数据包装动作来说:

  • 如果是使用知名协议,这个动作也称为封装
  • 如果是使用小众协议(包括自定义协议),这个动作也称为序列化,一般是将程序中的对象转换为特定的数据格式。

接收端应用程序,接收数据时的数据转换,即对接收数据时的数据解析动作来说:

  • 如果是使用知名协议,这个动作也称为分用
  • 如果是使用小众协议(包括自定义协议),这个动作也称为反序列化,一般是基于接收数据特定的格式,转换为程序中的对象

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

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

相关文章

【jvm】虚拟机栈之操作数栈

目录 一、说明二、图解2.1 代码示例2.2 javap操作 三、图示3.1 bipush 153.2 istore_13.3 bipush 83.4 istore_23.5 iload_13.6 iload_23.7 iadd3.8 istore_33.9 return结束 四、附加 一、说明 1.Operand Stack 2.栈可以使用数组或链表来实现 3.每一个独立的栈帧包含一个后进先…

arcgis js api 4.x通过TileLayer类加载arcgis server10.2发布的切片服务跨域问题的解决办法

1.错误复现 2.解决办法 2.1去https://github.com/Esri/resource-proxy 网站下载代理配置文件&#xff0c;我下载的是最新的1.1.2版本&#xff0c;这里根据后台服务器配置情况不同有三种配置文件&#xff0c;此次我用到的是DotNet和Java. 2.2 DotNet配置 2.2.1 对proxy文件增加…

相交链表-力扣

一、题目描述 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、题解 注意题目所说的相交&#xff0c;相交节点不只是数值上的相等&#xff0c;而是相交以后两条链变成一条链。 解决改题目&#xff0c;我们可以&#xff1a;…

景联文科技提供4D-BEV标注工具:提升自动驾驶感知能力的精准数据支持

4D-BEV标注是一种用于自动驾驶领域的数据标注方法。在3D空间的基础上&#xff0c;加入了时间维度&#xff0c;形成了四个维度。这种方法通过精准地跟踪和记录动态对象&#xff08;如车辆、行人&#xff09;的运动轨迹、姿势变化以及速度等信息&#xff0c;全面理解和分析动态对…

Java中JVM、JRE和JDK三者有什么区别和联系?

任何语言或者软件的运行都需要环境。就像人要生活在空气中&#xff0c;鱼要活在水中&#xff0c;喜阴植物就不能放在阳光下暴晒一样&#xff0c;任何对象个体的存在都离不开其所需要的环境&#xff0c;编程语言亦是一样的。 java 语言的开发运行&#xff0c;也离不开 Java 语言…

crossover23.6闪亮登场发布啦,2023最新功能解析

CrossOver刚刚更新了23.6版本&#xff0c;新增了多款游戏的支持&#xff0c;快来看看你想玩的游戏在不在里面吧。点击这里立即下载最新版CrossOver。 软件介绍 CrossOver 23.6 让Mac可以运行Windows程序的工具 已通过小编安装运行测试 100%可以使用。 CrossOver for Mac 23.…

OKLink携手CertiK在港举办Web3生态安全主题论坛

2023年10月23日&#xff0c;OKLink与CertiK共同发起的Web3生态安全主题论坛在香港铜锣湾拉开帷幕。本次论坛由OKLink和CertiK主办&#xff0c;香港投资推广署独家支持&#xff0c;聚焦如何构建安全可靠的Web3生态系统议题&#xff0c;同时深入剖析这一进程中所面临的潜在挑战。…

企事业单位/公司电脑文件透明加密保护 | 防泄密软件\系统!

推荐——「天锐绿盾电脑文件防泄密系统」 一款全面的企业/公司数据透明加密防泄密系统&#xff0c;旨在从源头上保障数据的安全和使用安全。 PC访问地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 它具有以下特点&#xff1a…

第6周 .NET

好嘛&#xff01;本来以为上周SQL Server环境配置等已经够恶心了&#xff0c;没想到这周又得去搞所谓的Microsoft Visual Studio 2005了。 首先非常离谱的是&#xff0c;这个Microsoft Visual Studio 2005如果就是指Visual Studio 2005&#xff0c;那么已经是8年前的老的不行的…

TensorFlow图像多标签分类实例

接下来&#xff0c;我们将从零开始讲解一个基于TensorFlow的图像多标签分类实例&#xff0c;这里以图片验证码为例进行讲解。 在我们访问某个网站的时候&#xff0c;经常会遇到图片验证码。图片验证码的主要目的是区分爬虫程序和人类&#xff0c;并将爬虫程序阻挡在外。 下面…

Python超入门(6)__迅速上手操作掌握Python

# 26.函数和参数 # 注意&#xff1a;有参函数和无参函数的名字要不同 def user(): # 无参函数print("hello world!")def user1(my_id): # 有参函数print(my_id)def user2(first_name, last_name): # 有参函数print(fMy name is {first_name} {last_name})print(&…

【机器学习】迁移学习(Transfer)详解!

1. 什么是迁移学习 迁移学习(Transfer Learning)是一种机器学习方法&#xff0c;就是把为任务 A 开发的模型作为初始点&#xff0c;重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务&#xff0c;虽然大多数机器学习算法都是…

微信小程序云开发笔记-初始化商城小程序

缘起&#xff1a;由于痴迷机器人&#xff0c;店都快倒闭了&#xff0c;没办法&#xff0c;拿出点精力搞一下店里的小程序&#xff0c;要多卖货才能活下来搞机器人&#xff0c;在此记录一下搞小程序的过程&#xff0c;要不然搞完又忘了。腾讯的云开发&#xff0c;前端和后端都有…

Linux阻塞IO(高级字符设备二)

阻塞IO属于同步 IO&#xff0c;阻塞IO在Linux内核中是非常常用的 IO 模型&#xff0c;所依赖的机制是等待队列。 一、等待队列介绍 在 Linux 驱动程序中&#xff0c;阻塞进程可以使用等待队列来实现。等待队列是内核实现阻塞和唤醒的内核机制&#xff0c;以双循环链表为基础结…

C笔记:引用调用,通过指针传递

代码 #include<stdio.h> int max1(int num1,int num2) {if(num1 < num2){num1 num2;}else{num2 num1;} } int max2(int *num1,int *num2) {if(num1 < num2){*num1 *num2; // 把 num2 赋值给 num1 }else{*num2 *num1;} } int main() {int num1 0,num2 -2;int…

SLAM从入门到精通(三边测量法详解)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 三边测量&#xff0c;或者说叫三角定位&#xff0c;是定位系统中很常见的一种测量方法。它最主要的原理就是依靠已有的三个特征坐标和半径&#xf…

Windows10系统安装telnet命令

简介 telnet命令可以测试目标服务器端口是否开通&#xff0c;使用命令 telnet ip地址 端口&#xff0c;输入命令后回车&#xff0c;如果进入输入状态&#xff0c;则表示目标服务器端口已开通&#xff0c;可以通过外网访问 Windows10系统安装步骤 1.打开控制面板 2.选择程序…

Hadoop3教程(三十一):(生产调优篇)异构存储

文章目录 &#xff08;157&#xff09;异构存储概述概述异构存储的shell操作 &#xff08;158&#xff09;异构存储案例实操参考文献 &#xff08;157&#xff09;异构存储概述 概述 异构存储&#xff0c;也叫做冷热数据分离。其中&#xff0c;经常使用的数据被叫做是热数据&…

Python Opencv实践 - 车辆统计(2)检测线绘制,车辆数量计数和显示

针对我所使用的视频&#xff0c;对上一节的代码进行了修改&#xff0c;增加了更多参数。 Python Opencv实践 - 车辆统计&#xff08;1&#xff09;读取视频&#xff0c;移除背景&#xff0c;做预处理_亦枫Leonlew的博客-CSDN博客示例中的图像的腐蚀、膨胀和闭运算等需要根据具…

操作系统-浅谈CPU与内存

目录 计算机的基本组成CPU内存虚拟内存内存分段内存分页 CPU与内存的交互过程高速缓存cache 所有图片均来自&#xff1a;小林coding 计算机的基本组成 计算机由软件和硬件组成 硬件由CPU(中央处理器&#xff09;存储器(内存外存&#xff09;外部设备组成。 软件由应用软件和系…