当前位置: 首页 > news >正文

详解:TCP/IP五层(四层)协议模型

一.五层(四层)模型

1.概念

TCP/IP协议模型分为五层:物理层、数据链路层、网络层、传输层和应用层。这五层每一层都依赖于其下一层给它提供的网络去实现需求。

1)物理层:这是最基本的一层,也是最接近硬件的一层。其规定了网络通信中的一些硬件设施要求。

2)数据链路层:完成两个相邻设备之间的如何进行通信。如通过网线把电脑链接到路由器/交换机上,这里的电脑与路由器/交换机就是相邻的设备。

3)网络层:完成两个任意设备之间的如何进行通信,考虑的是通讯中间的过程是怎么样的。

4)传输层:完成两个任意设备之间的如何进行通信,考虑的是通讯的起点和终点。

5)应用层:网络编程实现我们想要的效果(需求)。

举个形象例子:网购。我们可以将网购送货分成各个层次。首先最基础的,运货要有路,这个公路就是最基础的“物理层”。再说,快递员将货物运输到各个转运中心,这就是两个相邻的设备中间的通讯,是“数据链路层”。快递公司给快递小哥规划路线,让他怎么走,考虑的是中间的过程,这是“网络层”。网购商家只管填上发货地和收货地,其他不用管,不关心快递小哥是走哪几个转运中心的,只管能不能到收货地,这就是“传输层”。最后,快递到我们手里了,我们怎么使用是我们决定的,正如应用层代码是我们自己实现的,实现的是什么由我们自己决定,这就是“应用层”。

透过上面的例子大家应该对这五层模型是什么有了更深刻的印象了。

回答一下为什么有人说五层,有人说四层。说四层其实是将最下层的物理层和数据链路层合并成一个,与硬件设备直接相关,只是说法不同,实际上都是一样的。

2.网络设备所在分层

1)主机:通过应用程序满足网络通信的需求,涉及 物理层 -> 应用层。

2)路由器:组建局域网,进行网络数据包转发,涉及 物理层 -> 网络层。

3)交换机:对路由器接口的拓展,涉及 物理层 -> 数据链路层。

二.传输层协议

传输层有两个核心协议,一个是TCP,一个是UDP。

1.UDP

1)特点:无连接,不可靠传输,面向数据报,全双工。

UDP不保存通讯对端的信息,这就是无连接。UDP发出数据后直接就不管了,一点不可靠。UDP在读写数据的时候,是以一个数据报为单位去读写的,注意一次必须读写一个数据报,半个不行,因此不存在粘包问题(这个在下面的TCP会解释)。全双工的意思的能读也能写,与之对应的是半双工,只可以读或只可以写。

2)报文格式:

源端口号和目的端口号这两个好理解,就是起点和终点。

UDP长度指的是整个UDP的长度,包括报头和载荷,长度这个位置最多存储两个字节的数据,也就是整个UDP长度最长是64kb。如果我们传输的数据超过64kb,比较大,这个时候我们就要考虑拆包了传输了。

校验和用来验证数据是否发生修改。这个校验和不是用来保证数据安全的,而是用来防止数据在运输的过程中发生比特翻转的现象。比特翻转就是数据的比特位1变成0,0变成1。

UDP校验和使用了CRC(循环冗余校验)的方法,把每个字节都当作整数进行累加,不管溢出,直至最终,得到校验和。

数据在发出端计算一次校验和,再放入报文中,传给目的端,目的端再算一次校验和,看看两个是不是一样。如果是一样,只能确定可能没有发生比特翻转;而不一样,肯定是发生比特翻转了。

UDP在发现校验和不同时只会丢弃,不会重发,如果要重发要我们自己写代码实现。

2.TCP

1)特点:有连接,可靠传输,面向字节流,全双工。

TCP会保存对端的信息,这就是有连接。TCP有两个核心机制保证其是可靠传输。TCP在读写数据的时候是以字节为单位的,支持任意长度,因此存在粘包问题。TCP支持读也支持写。

2)报文格式:

TCP报文内容与TCP的核心机制有关,具体各个部分是什么在下面解释。这里只是补充下面没有提到的。

16位紧急指针(URG)在标志位处有,用来跳过前面的数据,直接从某一个开始读。

PSH(催促标志位)发送方给接收方的数据中带有这个标志,接收方会尽快的将这个数据read。

3.TCP十大核心机制

1)确认应答

在日常生活中,我们怎判断我们叫了某个人他有没有听见,他回应一声不就行了。

TCP也是这么想的,我们在发送数据后,需要对方给一个应答报文(acknowledge,简称ack)。我们收到了这个ack后,就知道了目的端已经收到数据了。这就是TCP是可靠传输的一大原因。

但是在数据传输时可能会出现先发后到的情况。我们在发送数据后,这个数据会经过多个路由器/交换机。每个数据走的路线不同,可能先发的数据走的“路”比较长,花的时间更长,导致“来的比较完”。

针对这种情况,TCP会对载荷中的每个字节进行编号,32位序号就是载荷部分第一个字节的序号,序号连续递增。

32位确认序号的目的就是告诉发送者,我已经收到了那些数据,下次发送从确认序号这个位置开始发。32位确认序号的值就是收到的数据载荷的最后一位+1。注意,这个32位确认序号只在应答报文中生效。

那怎么才能知道这个TCP是应答报文?这就是上面标志位(下图)管的了。

可以看到第二个表示位是ACK,也就是应答报文的意思,如果这一位是 1 ,说明这个报文就是应答报文。

说回来,有了序号之后,应用程序会通过socketAPI读到正确的顺序,不用担心先发后到的情况了。

2)超时重传

超时重传是针对丢包问题进行的处理。丢包问题是不可避免的客观情况。

TCP规定了一个超时时间阈值,这个阈值不是固定不变的,是动态变化的。如果超过这个阈值就是触发重传,同时延长这个时间阈值。但是这个重传和时间阈值是有上限的,超过这个上限后就是放弃传输。

一次信息传输可能有两种丢包情况:

情况一:源端口发送的数据丢失,这个时候直接重传就可以了。

情况二:目的端发送的ack丢失,源端口迟迟没有收到ack,会认为是自己发送的数据丢失,重发一次。这时目的端会收到相同的数据,TCP有一个接收缓存区,数据会先到缓存区,如果发现数据已经存在了就丢弃,如果没有就放入。

3)连接管理

连接分为建立连接和断开连接。

TCP建立连接是通过“三次握手”来实现的。

syn(synchronized,同步)表示的是同步报文,在上图表示为中有,如果syn是1的话,表示这个报文是同步报文。当然,一个报文可以既是同步报文也是应答报文。

建立连接的过程:1. A先给B发一个同步报文。2. B收到后会给A发一个同步报文同时发一个应答报文,这两个报文可以分开,但没必要,因为这两个都是内核负责的,可以保证同一时机。3. A收到同步报文和应答报文后会发给B一个应答报文。 

三次握手的作用:1.探一探网络的通信链路是否通畅,这个网络可靠传输的前提条件。2.验证双发的发送能力和接收能力是不是正常。3.协商关键信息,比如通讯序号从几开始。

TCP断开连接是通过“四次挥手”来实现的。

FIN(finish,完成),表示发送方已经没有数据要发送了,请求断开连接,FIN位为1表示FIN报文。FIN不是由内核负责,而是与我们写的程序有关,代码中调用socket.close或进程结束时才会发送。

断开连接的过程:1.A给B发一个FIN,请求断开连接。2.B给A一个ACK,表示收到A的请求。3.等到B的逻辑执行完了,给A发送FIN,B请求断开连接。4.A给B发一个ACK,表示收到B的请求。

下图是整个连接的全过程

介绍一下上图中出现的部分状态的含义:

ESTABLISHED:连接完成,可以发送数据了。

CLOSE_WAIT:被发起FIN的一方进入该状态,表示等待程序调用close方法。

TIME_WAIT:主动发起FIN的一方进入该状态,表示等待对方结束。主动发起方不会一直等待对方发FIN,而是由一个等待上限,上限时间是2*MSL(网络上两个任意节点传输过程中消耗的最大时间)。

4)滑动窗口

前面说TCP采用一问一答的方法来进行数据传输,这个其实效率比较低。如果我们一下发好几个,不用等待应答,这样就可以提高效率。我们一下发出好几个后,返回一个应答,就再发送下一条。这个不就是滑动窗口嘛。

窗口越大,批量发的数据越多,效率就越高。但是窗口不能无限大,太大了会影响可靠性。

滑动窗口丢包的情况:

这个问题不大,超时后重传。

 正如上图说的那样,1001-2000的数据丢了后,主机B没有收到这个数据,其会再应答报文的确认序号哪里一直返回1001。主机A连续3次收到相同的确认序号时会意识到1001-2000这部分数据丢失了,会重发1001-2000。已经发的2001-7000受不受影响呢?答案是不受影响,为什么?

前面说了,在读数据的时候会按顺序读数据,读到1001,发现没有,队列堵塞,后面的数据一直堵在哪里,等到1001-2000来了后才继续读。这个队列不是一个纯粹的队列,我们发的每个数据都是有序号的,可以根据这个序号来准确的算出数据应该放的位置,如果没有就空着这个位置。

这种重传的方式叫快速重传,即只传丢了的数据,不传其他数据。注意快速重传是在滑动窗口下出现的,不要弄错情况。

5)流量控制

前面说了窗口越大,效率越高,但窗口过大,就是影响可靠性。为了提高效率的同时保证传输可靠性,TCP对流量进行了控制。

TCP有一个接收缓冲区,里面有一些待处理的数据。进入缓冲区的速度取决于发送方发送的速度,出缓冲区的速度取决于应用程序读取的速度。TCP可以根据处理数据的速度,反馈给发送方,限制它的发送速度。

怎么做到的?滑动窗口的大小会动态变化。在TCP的报文中有一栏就是滑动窗口的大小。

这个窗口的大小等于 接收缓冲区剩余空间的大小。剩的多了,就多放进来一点;剩的少了,就少放一点呗。

一旦发现返回的窗口的大小是0,发送方就会暂停发送,过一段时间发送一个窗口探测包,“问问”接收方的接收缓存区有没有空间,有空间了,继续传输数据。

6)拥塞控制

上面说的流量控制是依据接收的处理能力进行限制。而拥塞控制是依据传输链路的转发能力进行限制的。它通过不断试验的方法区找到一个合适的窗口大小,大了就减,小了就加,说白了就是“面多加水,水多加面”。

拥塞机制的工作过程:

先慢启动,再指数增长,再线性增长。发现丢包了,窗口减小,回到新的阈值处。

7)延时应答

默认情况,发送方发送数据后会立即返回ack,但是如果我们延时发送ack,效率会提高。

如果延时发送,接收缓冲区的数据会被处理更多,这个时候返回ack,会返回更大的滑动窗口大小。我们知道窗口越大,效率越高,这样延时发送就会提高效率。

所有包都可以延时应答吗?不是。有数量限制,每隔N个包就要应答一次。也有时间限制,超过最大延迟时间就应答一次。

8)捎带应答

基于延时应答,TCP可以将上次的ack捎并带回,这样将两个包放在一起传输,提高了效率。

9)面向字节流

前面在介绍TCP的特点的时候就提到了一点,因为TCP是面向字节流传输的,支持任意长度,因此就有粘包问题。

什么是粘包问题?粘包问题粘的是应用层数据包,各个包之间由于没有长度限制,而且是面向字节流,不是数据报,因此有时候会分不清字节要读到哪里停止,会出现多读或漏读的情况。粘包问题在TCP层面是无解的,我们要在应用层方面区解决这个问题。定义好应用层的协议,明确包之间的边界。

10)异常情况的处理

TCP通讯过程中会出现的特殊情况。

情况一:  进程崩溃/主机关机

本质上与主动退出没有区别

情况二:  主机断电/网线断开

分为接收方断电和发送方断电。

接收方断电:发送方发送的数据没有ack返回,超时重传后还没有返回。重传到一定次数会触发“重置TCP连接”,发送方会主动发一个复位报文(RST),如果还没有用,发送方就会单方面释放连接。

发送方断电:发送方断电后,接收方此时判断不出来发送方是断电了还是暂时没有数据发送。等待一段时间后接收方会发送一个特殊报文—“心跳包”,这个报文不携带数据,只是为了触发ack,跟上面的窗口探测一样。如果不跳了,就发一个复位报文,如果还不好使,就单方面释放连接。

三.网络层协议

1.IP协议基础

概念:用于唯一标识网络中的每台计算机。我们可以在cmd中查看ip地址:ipconfig。

IP地址的表示形式:点分十进制 xx.xx.xx.xx,每个十进制数的范围是0—255。

IP地址的组成:网络地址+主机地址。

同一个局域网当中网络地址必须相同,主机地址必须不同。相邻的局域网中网络地址必须不同,主机地址随意。

Ipv4是由4个字节(32位)表示,而I,Pv6是由16个字节(128位)表示。

IP协议的作用主要是下面两个:

1)地址管理,用来标识网络上的某个设备的位置。

2)路由选择,在两个通信的节点之间,规划出一个合理的路径。

这是以前使用的IPv4地址分类,现在不用了:

各类表示范围:

那现在的IPv4怎么分网络号和主机号呢?

打开ipconfig:

看到下面的子网掩码,255的表示网络地址位,0表示主机地址位。

特殊的IP地址:

1)将IP地址中的主机地址全部设成0就成了网络号,代表这个局域网

2)将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包

3)127.*的IP地址用于本机环回(loop back)测试,通常是127.0.0.1

2.IP协议报文

1)4位版本:IPv4或IPv6

2)4位首部长度:因为报头有选项这一栏,所以报头长度也是变长的

3)8位服务类型:决定了IP地址的工作方式,3位优先权字段(已弃用)+ 4位TOS字段 + 1位保留字段(必须设置为0)。4位TOS字段分别表示:最小延时,最大吞吐量,最高可靠性,最小成本。注意这四个TOS字段是不共存的,只能是其中一个,要根据实际情况选择。

4)16位总长度(字节数):报头+载荷的长度

5)16位标识、3位标志,13位片偏移:

IP协议内置了拆包组包的功能,拆完了包我们要给包一个标识,要不然怎么组包,怎么知道谁跟谁是一组的。16位标识位就是给包一个标识,拆出来的包都是一个标识,组包的时候就将相同标识的包组在一起。3位标志用来标志有没有触发拆包操作,并且记录这个包是不是最后一个包。13位片偏移描述了先后顺序,偏移小的放在前面,偏移大的放在后面

6)8位生存空间(TTL):一个IP数据报能在网络上传输的最大时间,单位是次数,IP数据报每经过一个路由器就TTL就减小一次

7)8位协议:标识传输层使用什么协议

3.NAT机制

NAT机制,即网络地址转换,是当今网络时间解决IPv4不够用的最重要的方式。

其将说有IP分成两类:一是公网/外网,另一是私网/内网。公网IP是唯一的,但是私网IP在不同的局域网中是可以重复的。

如上面的例子,运营商路由器具有NAT功能,能将我的设备的IP地址进行转换:192.168.100.1->100.1.1.1。

可能会有多个设备对运营商的服务器发送请求,但是到了运营商的路由器都会被转换成同一个IP

服务器收到请求后会返回给运营商路由器。但是运营商怎么知道这个哪一个设备发送的请求呢?

运营商在地址转换时会将两个地址存入一个记录映射关系的表格,记录替换前的地址和替换后的地址,同时也会记录端口。NAT设备进行转换的时候可以修改端口号,这一就避免了端口相同找不到源地址的情况。

4.路由选择

这里介绍路由选择的简单模型:探索式。

网络环境是非常复杂的,路由器没有办法将所有的网络信息都存储,只存储周围的网络情况。当数据包到了某个路由器,就会匹配这个路由器的路由表。路由表中记录了这个路由器周围的设备的IP地址是什么,以及记录每个设备要通过哪个口转发过去。

如果目的IP地址刚好匹配到了路由表中的记录,就直接转发到对应的口。

如果没有匹配到,路由表会有一个特殊的表项——下一跳,指向的设备就是上一级路由器所在的位置。

四.数据链路层

1.以太网

以太网帧格:

1)目的地址和源地址这里存储的地址不是IP地址,而是mac地址(物理地址)。

想看这个地址要在cmd中输入:ipconfig /all

2)类型是用来确定载荷的数据格式的

3)CRC:帧尾,校验和

4)ARP:根据IP地址,得到对应的mac地址。具体做法:通过广播地址,发送ARP数据报,询问周围的网络设备的IP地址和mac地址,路由器会构建出一个映射表来存储这些IP地址和ARP地址

五.应用层

1.DNS

可以认为是应用层的一个协议也可以认为是一个系统。这个系统就是域名解析系统(域名是什么在后面的网络基础知识中有)。

最初DNS通过一个hosts文件,这个文件中存储域名和IP地址的映射关系。我们在访问某个网站的时候,会先查询DNS服务器,把域名对应的IP拿到,再访问服务器。

现在全世界的服务器这么多,我们都访问DNS服务器,服务器会承受海量的并发量,容易挂。

这里有两个方法去解决:

1)缓存,我们再DNS服务器找到IP地址后会存储再缓存中,下次访问这个域名就不用去DNS服务器查找了

2)DNS服务器有很多,存储原始数据的是根服务器,各个网络运营商可以搭建镜像服务区。

2.InetAddress类

常用方法:

方法说明
getLocalHost获取本机InetAddress对象
getByName

根据主机名/域名 获取InetAddress对象

getHostName获取InetAddress对象的主机名
getHostAddress获取InetAddress对象的地址

代码示例:

//1.获取本机的InetAddress对象
InetAddress localHost = InetAddress.getLocalHost();
//输出设备名称和IP
System.out.println(localHost);//2.根据主机名 获取InetAddress对象
InetAddress host1 = InetAddress.getByName("LAPTOP-RPIOC01F");
System.out.println(host1);//3.根据域名 获取InetAddress对象
InetAddress host2 = InetAddress.getByName("www.bilibili.com");
System.out.println(host2);//4.通过 InetAddress 对象,获取对应的地址
String hostAddress = host2.getHostAddress();
System.out.println(hostAddress);//5.根据 InetAddress 对象,获取对应主机名/域名
String hostName = host2.getHostName();
System.out.println(hostName);

3.TCP网络通信

1)Socket

Socket开发网络应用程序被广泛采用,以至于成为事实上的标准。通信的两端都要有Socket,是两台机器间通信的端点。网络通信其实就是Socket间的通信。

Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。

一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。

怎么理解这个Socket呢?可以从它的英文原意入手,socket->插座、插口。它就是一个插口,中间连接一个数据通道

2)使用字节流

代码示例:

//客户端//1.连接服务器(ip,端口),如果连接成功返回Socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
System.out.println("客户端返回:"+socket.getClass());
//2.连接上后,生成Socket对象,通过socket.getOutputStream()得到和socket对象关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//3.通过输出流,写入数据到数据通道
outputStream.write("hello".getBytes());
//4.设置结束标记
socket.shutdownOutput();
//5.关闭流对象
outputStream.close();
socket.close();
System.out.println("客户端退出");
//服务端//1. 在本机的9999端口监听,等待连接
//要求在本机没有其他服务在监听9999
//这个 ServerSocket 通过accept() 返回多个Socket
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端在9999端口监听,等待中。。。");
//2.当没有客户端连接9999端口时,程序会阻塞,等待连接
// 如果有客户端连接,则会返回Socket对象,程序继续
Socket socket = serverSocket.accept();
//3.通过 读取客户端写入到数据通道的数据
InputStream inputStream = socket.getInputStream();
//4.IO读取
byte[] bf=new byte[1024];
int readLen=0;
while((readLen=inputStream.read(bf))!=-1){System.out.println(new String(bf,0,readLen));
}
//5.关闭流
inputStream.close();
socket.close();
serverSocket.close();

3)使用字符流传输文件

代码示例:

//客户端//1.连接服务端,得到Socket对象
Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
//2.创建读取磁盘文件的输入流
String path="C:\\JavaNet\\Java.png";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
//将文件内容读入数组中
byte[] bytes=StreamUtils.streamToByteArray(bis);
//3.传输到服务端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);
bis.close();
socket.shutdownOutput();    //设置写入数据结束//4.接收消息
InputStream inputStream = socket.getInputStream();
byte[] b=new byte[1024];
int readLen=0;
while ((readLen=inputStream.read(b))!=-1){System.out.println(new String(b,0,readLen));
}
//5.关闭流
inputStream.close();
bos.close();
socket.close();
//服务端//获得端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端在8888端口等待...");
//等待连接
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//拿到文件
byte[] bytes=StreamUtils.streamToByteArray(bis);
String path="C:\\JavaNet\\pic.png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
bos.write(bytes);
bos.close();//发送信息
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("已收到图片");
writer.flush();         //刷新内容到数据通道
socket.shutdownOutput();
System.out.println("已收到图片");//关闭资源
writer.close();
bis.close();
socket.close();
serverSocket.close();

4)补充

使用缓冲流一定注意要刷新数据到数据管道,否则就白写了。

在写入完后一定要记得设置写入数据结束。

4.UDP网络通信编程

1)基本流程

核心的两个类/对象 DatagramSocket 与 DatagramPacket;建立发送端,接收端;发送数据前,建立数据包DatagramPacket对象;调用DatagramSocket的发送接收方法;最后关闭DatagramSocket。

2)应用

代码示例:

//发送端//1.创建DatagramSocket对象,准备在9998接收数据
DatagramSocket socket = new DatagramSocket(9998);
//2.将需要发送的数据,封装到对象
byte[] data="秘制小汉堡".getBytes();
//说明:封装 DatagramPacket 对象,data ,长度,主机IP,端口
DatagramPacket packet =new DatagramPacket(data, data.length, InetAddress.getByName("10.40.91.181"),9999);
socket.send(packet);
socket.close();
System.out.println("B结束了");
//接收端//1.创建一个DatagramSocket对象,准备在9999接收数据
DatagramSocket socket = new DatagramSocket(9999);
//2.构建一个 DatagramPacket对象,准备接收数据
byte[] buf=new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
//3.准备接收数据,将通过网络传输的DatagramPacket对象填充到packet对象
//有数据就会接收,没数据就会阻塞
System.out.println("正在等待连接");
socket.receive(packet);
//4.可以把packet 进行拆包,取出数据,并显示
int length=packet.getLength();  //实际接收的数据字节长度
byte[] data=packet.getData();
String regStr = new String(data, 0, length);
System.out.println(regStr);
//关闭资源
socket.close();
System.out.println("A结束");

 六.网络的基础概念

1.网络通信

两台设备之间通过网络实现数据传输,将数据通过网络从一台设备传输到另一台设备。

在java.net包下提供了一系列的类或接口,供程序员使用完成网络通信。

2.网络

两台或多台设备通过一定物理设备连接起来构成了网络。

根据网络的覆盖范围可分为下面几类:

1)局域网:覆盖范围最小,仅仅覆盖一个教室

2)城域网:覆盖范围较大,可以覆盖一个城市

3)广域网:覆盖范围最大,可以覆盖全国

3.域名和端口号

域名概念:将IP地址映射成域名,也就是将IP地址变成了网站。IP地址一堆数字,太难记了,转变成域名后方便记忆。

端口号概念:用于标识计算机上某个特定的网络程序。我们可以通过端口号来访问某一个域名下的某个服务。ip定位主机,端口定位服务。比如说我们访问了B站的域名,要想连上网站服务,就需要一个端口号来实现。

端口号就好像是房子的门,如果我们想要进入房子就要通过门。一个房子可能有多个门,同样一个主机也有多个端口号,每个端口号都对应着其自身的业务。

端口号表示形式:以整数的形式,范围0—65535(2个字节表示端口)

避免使用0—1024端口,因为0—1024都被占用了。常见的网络程序端口号:tomcat:8080  mysql:3306  Oracle:1521  sqlserver:1433。

相关文章:

详解:TCP/IP五层(四层)协议模型

一.五层(四层)模型 1.概念 TCP/IP协议模型分为五层:物理层、数据链路层、网络层、传输层和应用层。这五层每一层都依赖于其下一层给它提供的网络去实现需求。 1)物理层:这是最基本的一层,也是最接近硬件…...

(七)Mapbox GL JS 表达式初识

以下是关于如何在 Mapbox GL JS 中使用表达式的详细讲解和代码示例。 文章目录 什么是 Mapbox GL JS 表达式?使用场景步骤1. 初始化地图2. 解释表达式 总结 什么是 Mapbox GL JS 表达式? Mapbox GL JS 表达式是一种灵活的样式语言,允许你在 …...

阿里巴巴开发规范手册MySQL

1、MySQL 数据库 1.1、建表规约 1) 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint(1 表示是,0 表示否)。 说明:任何字段如果为非负数,必须是 unsigned。 注…...

SpringCloud微服务Gateway网关简单集成Sentinel

Sentinel是阿里巴巴开源的一款面向分布式服务架构的轻量级流量控制、熔断降级组件。Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来帮助保护服务的稳定性。 官方文档:https://sentinelguard.io/zh-cn/docs/introduction.html …...

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到 这次在windows的WSL2中遇到了一个非常奇怪的错误,就是 CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):Could NOT find BLAS (missing: BLAS_LIBRAR…...

私有IP、VLAN和VPC,分别适合哪些场景你知道吗?

当我们在云中构建应用程序,尤其是使用了第三方云服务商的服务并且我们无法完全掌控后端的每部分时,安全性可能是最需要关注的地方。但这是一项充满挑战的工作,因为保护应用程序的方法实在是太多了!为了改善安全性,开发…...

【学术会议论文投稿】深度解码:机器学习与深度学习的界限与交融

目录 一、定义与起源:历史长河中的两条轨迹 二、原理差异:从浅层到深层的跨越 三、代码解析:实战中的机器学习与深度学习 机器学习示例:线性回归 深度学习示例:卷积神经网络(CNN) 四、应用差异:各自领…...

一位前端小白的2024总结

目录 简要 一、迷茫点的解决 (1)前端领域该怎么学? (2)旧技术还需要学吗? (3)我该学些什么? 二、折磨点的解决 (1)学技术成果回报太慢怎么…...

状态模式——C++实现

目录 1. 状态模式简介 2. 代码示例 3. 单例状态对象 4. 状态模式与策略模式的辨析 1. 状态模式简介 状态模式是一种行为型模式。 状态模式的定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。 通俗的说就是一个对象…...

C# 控制打印机:从入门到实践

在开发一些涉及打印功能的应用程序时,使用 C# 控制打印机是一项很实用的技能。这篇文章就来详细介绍下如何在 C# 中实现对打印机的控制。 一、准备工作 安装相关库:在 C# 中操作打印机,我们可以借助System.Drawing.Printing命名空间&#x…...

【一个按钮一个LED】用STM32F030单片机实现苹果充电器的定时装置

文章目录 前言一、要实现的功能1、循环定时2、倒计时3、指示灯提示4、使用场景二、实现方法1、使用方法2、电路设计三、程序代码和成品1.定时中断子程序2.键值处理3.主函数总结前言 笔者前几年买苹果手机、IPAD配的适配器是A1443型号,这种5V1A,USB-A口、小功率的适配器,苹果…...

ansible自动化运维实战--script、unarchive和shell模块(6)

文章目录 一、script模块1.1、功能1.2、常用参数1.3、举例 二、unarchive模块2.1、功能2.2、常用参数2.3、举例 三、shell模块3.1、功能3.2、常用参数3.3、举例 一、script模块 1.1、功能 Ansible 的 script 模块允许你在远程主机上运行本地的脚本文件,其提供了一…...

LLM大模型实践18-评估(上)——存在一个简单的正确答案

准备数据 products_and_category { "电脑和笔记本": [ "TechPro 超极本", "BlueWave 游戏本", "PowerLite Convertible", "TechPro Desktop", "BlueWave Chromebook" ], "智能手机和配件": [ "…...

力扣-数组-704 二分查找

解析 经典二分&#xff0c;重点在于左闭右闭区间约定好后&#xff0c;根据定义更新边界 代码 class Solution { public:int search(vector<int>& nums, int target) {int left 0, right nums.size() - 1;while(left < right){int mid (left right) / 2;if(…...

K8S 快速实战

K8S 核心架构原理: 我们已经知道了 K8S 的核心功能:自动化运维管理多个容器化程序。那么 K8S 怎么做到的呢?这里,我们从宏观架构上来学习 K8S 的设计思想。首先看下图: K8S 是属于主从设备模型(Master-Slave 架构),即有 Master 节点负责核心的调度、管理和运维,Slave…...

C#集合操作优化:高效实现批量添加与删除

在C#中&#xff0c;对集合进行批量操作&#xff08;如批量添加或删除元素&#xff09;通常涉及使用集合类型提供的方法和特性&#xff0c;以及可能的循环或LINQ查询来高效地处理大量数据。以下是一些常见的方法和技巧&#xff1a; 批量添加元素 使用集合的AddRange方法&#x…...

Unity|小游戏复刻|见缝插针1(C#)

准备 创建Scenes场景&#xff0c;Scripts脚本&#xff0c;Prefabs预制体文件夹 修改背景颜色 选中Main Camera 找到背景 选择颜色&#xff0c;一种白中透黄的颜色 创建小球 将文件夹里的Circle拖入层级里 选中Circle&#xff0c;位置为左右居中&#xff0c;偏上&…...

【Redis】持久化机制

目录 前言&#xff1a; RDB 触发RDB持久化方法有俩种&#xff1a; 1.手动触发 2.自动触发 RDB文件的优缺点&#xff1a; AOF: AOF工作机制&#xff1a;​编辑 ​编辑重写机制&#xff1a; 前言&#xff1a; Redis是一个内存数据库&#xff0c;将数据存储在内存中&…...

AWScurl笔记

摘要 AWScurl是一款专为与AWS服务交互设计的命令行工具&#xff0c;它模拟了curl的功能并添加了AWS签名版本4的支持。这一特性使得用户能够安全有效地执行带有AWS签名的请求&#xff0c;极大地提升了与AWS服务交互时的安全性和有效性。 GitHub - okigan/awscurl: curl-like acc…...

5_高并发内存池项目内存优化、页号与Span映射关系使用基数树优化及测试性能与malloc、free比较

申请/释放 内存大小申请方式释放方式x≤256KB&#xff08;32页&#xff09;向ThreadCache申请释放给ThreadCache32页<x≤128页向PageCache申请释放给PageCachex&#xff1e;128页向堆申请释放给堆 一、解决大于256KB的大块内存申请 &#xff08;一&#xff09;申请大于256…...

深入剖析C++中cin的原理、应用与进阶实践

一、引言 1.1 研究背景与目的 在 C 编程领域&#xff0c;cin 作为标准输入流对象&#xff0c;扮演着举足轻重的角色&#xff0c;是实现程序与用户交互的关键工具。它允许程序从标准输入设备&#xff08;通常是键盘&#xff09;读取数据&#xff0c;并将其存储到程序变量中&am…...

我国的金融组织体系,还有各大金融机构的分类,金融行业的组织

中国金融组织体系介绍 中国金融组织体系是一个复杂而多层次的系统&#xff0c;涵盖了各种类型的金融机构和监管机构。以下是关于中国金融组织体系的详细介绍&#xff0c;包括一行三会等金融监管机构&#xff0c;各大金融机构的分类、涉及的银行以及行业组织。 &#xff08;一…...

十三、数据的输入与输出(4)

数据的输出 write.table()函数 write.table&#xff08;&#xff09;函数的基本格式如下所示。 write.table(x, file "", quote TRUE, sep "", eol "\n", na "NA", dec ".", row.names TRUE, c…...

基于Java Web的网上房屋租售网站

内容摘要 本毕业设计题目为《基于Java Web的网上房屋租售网站》&#xff0c;是在信息化时代下充分利用互联网对传统房屋租售方式进行创新&#xff0c;在互联网上进行房屋租售突破了传统方式的局限性。对于房屋租售的当事人都提供了极大的便利。本稳针对了实际用户需求&#xf…...

【MySQL — 数据库增删改查操作】深入解析MySQL的create insert 操作

数据库CRUD操作 1 CRUD简介 CURD是对数据库中的记录进行基本的增删改查操作: 2. Create 新增 语法 INSERT [INTO] table_name[(column [&#xff0c;column] ...)] VALUES(value_list)[&#xff0c;(value_list)] ... # value 后面的列的个数和类型&#xff0c;要和表结构匹配…...

问题修复记录:Linux docker 部署 dify,无法调用宿主机本地服务

使用docker compose启动Dify后,在其中配置本地xinfrence中的模型,报错: get xinference model extra parameter failed, url: http://127.0.0.1:9997/v1/models/bge-m3, error: HTTPConnectionPool(host=‘127.0.0.1’, port=9997): Max retries exceeded with url: /v1/mo…...

【橘子ES】Kibana的分析能力Analytics简易分析

一、kibana是啥&#xff0c;能干嘛 我们经常会用es来实现一些关于检索&#xff0c;关于分析的业务。但是es本身并没有UI,我们只能通过调用api来完成一些能力。而kibana就是他的一个外置UI&#xff0c;你完全可以这么理解。 当我们进入kibana的主页的时候你可以看到这样的布局。…...

如何理解json和json字符串

如何理解网络传输的json到底是什么数据 网络传输的其实是对应的 json字符串 对象&#xff0c;前端接收后会将 json字符串 解析成 json对象 json类型字符串和json对象或者json数组是不一样的&#xff0c;json类型字符串本质是字符串&#xff0c;而json对象是json类型的数据&…...

项目上线后,是否会进行复盘?

是的&#xff0c;定期复盘在软件测试项目里极为关键&#xff0c;我会按以下步骤开展复盘工作&#xff1a; 复盘周期确定 短期项目&#xff1a;针对周期较短&#xff08;如 1 - 2 个月&#xff09;的项目&#xff0c;会在项目结束后的一周内进行复盘&#xff0c;确保大家对项目…...

基于 WEB 开发的手机销售管理系统设计与实现内容

标题:基于 WEB 开发的手机销售管理系统设计与实现 内容:1.摘要 摘要&#xff1a;随着智能手机的普及和电子商务的快速发展&#xff0c;手机销售行业面临着越来越多的挑战和机遇。为了提高销售效率和管理水平&#xff0c;本文设计并实现了一个基于 WEB 的手机销售管理系统。该系…...

SpringBoot篇 单元测试 理论篇

1.单元测试概念介绍 简单来说&#xff0c;单元测试是对软件中的最小可测试单元进行检查和验证。在 Java 中&#xff0c;单元测试的最小单元是类。Spring Boot 提供了 spring-boot-starter-test 依赖&#xff0c;包含了 JUnit、Mockito、Hamcrest 等常用的测试框架1。&#xff0…...

并发编程 - 线程同步(一)

经过前面对线程的尝试使用&#xff0c;我们对线程的了解又进一步加深了。今天我们继续来深入学习线程的新知识 —— 线程同步。 01、什么是线程同步 线程同步是指在多线程环境下&#xff0c;确保多个线程在同时使用共享资源时不会发生冲突或数据不一致问题的技术&#xff0c;保…...

Nginx 性能优化技巧与实践(二)

五、性能优化之负载均衡篇 5.1 负载均衡算法介绍 Nginx 作为一款强大的 Web 服务器和反向代理服务器&#xff0c;其负载均衡功能是提升 Web 服务性能和可靠性的关键。Nginx 支持多种负载均衡算法&#xff0c;每种算法都有其独特的原理和特点&#xff0c;适用于不同的业务场景…...

解密AIGC三大核心算法:GAN、Transformer、Diffusion Models原理与应用

在当今数字化时代&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;技术正以前所未有的速度改变着我们的生活和工作方式。从创意无限的文本生成&#xff0c;到栩栩如生的图像创作&#xff0c;再到动听的音乐旋律&#xff0c;AIGC的魔力无处不在。而这一切的背后&#…...

qml Dialog详解

1、概述 Dialog是QML&#xff08;Qt Modeling Language&#xff09;中用于显示对话框的组件&#xff0c;它提供了一个模态窗口&#xff0c;通常用于与用户进行重要交互&#xff0c;如确认操作、输入信息或显示警告等。Dialog组件具有灵活的布局和样式选项&#xff0c;可以轻松…...

GL C++显示相机YUV视频数据使用帧缓冲FBO后期处理,实现滤镜功能。

一.前言&#xff1a; GitHub地址&#xff1a;GitHub - wangyongyao1989/WyFFmpeg: 音视频相关基础实现 系列文章&#xff1a; 1. OpenGL Texture C 预览Camera视频&#xff1b; 2. OpenGL Texture C Camera Filter滤镜; 3. OpenGL 自定义SurfaceView Texture C预览Camera视…...

一文了解树与森林基础

文章目录 树和森林1树的存储结构1.1双亲表示法1.2孩子表示法1.3孩子兄弟表示法 2树、森林与二叉树的转换2.1森林与二叉树的转换2.2 树与二叉树的转换 3树和森林的遍历3.1树的遍历3.2森林的遍历3.3 树和森林的遍历与二叉树的遍历关系 4树的应用——并查集4.1并查集及其相关操作4…...

在Docker 容器中安装 Oracle 19c

在 Docker 容器中安装 Oracle 19c 是可行的&#xff0c;但它相较于其他数据库&#xff08;如 MySQL、PostgreSQL 等&#xff09;会复杂一些&#xff0c;因为 Oracle 数据库有一些特定的要求&#xff0c;如操作系统和库的依赖&#xff0c;以及许可证问题。 不过&#xff0c;Ora…...

Java TCP协议(2)

TCP可靠传输 五. 流量控制 用来控制发送方的窗口大小&#xff0c;通过接收方返回来的ACK进行反制。 接收方把自己能够处理的数据量主动告诉发送方&#xff0c;从而让发送方动态调整窗口大小。 如果窗口大小为0表示没有空间去接收数据了&#xff0c;主机A就不发数据了&#xf…...

JS基础-操作数组(7)

一.增删改查 1.改 重新赋值 2.增 arr.puch() 末尾追加 arr.unshift() 开头追加 a)案例&#xff1a;数组筛选 3.删除 arr.pop() 删除最后一个元素 arr.shift() 删除第一个元素 splice&#xff08;&#xff09; 删除指定元素...

(长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)

城市三维建模与分析 三维城市模型已经成为一种非常普遍的地理空间数据资源,成为城市的必需品,对城市能化管理至关重要。语义信息丰富的三维城市模型可以有效实现不同领域数据与IS相信息的高层次集成及互操作,从而在城市规划、环境模拟、应急响应和辅助决策等众多领域公挥作用、…...

大数据技术笔记

大数据技术概述 本章初步介绍大数据领域技术涉及的一些基础理论&#xff0c;如分布式、存储、网络等知识。 分布式理论 大数据意味数据量大&#xff0c;那么存储和计算数据的节点就不大可能只有一个&#xff0c;而是采用分而治之的思想在多个节点中存储和计算&#xff0c;提…...

【JAVA 基础 第(20)课】JDBC JAVA 连接 MySql 数据库

pom.xml 导入 MySql jar 包 <!-- 导入Mysql数据库链接jar包 --> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.30</version> </dependency> 数据库驱动、连接封装成…...

如何将使用unsloth微调的模型部署到ollama?

目录 一、将模型保存为gguf格式 二、下载llama.cpp 三、生成 llama-quantize 可执行文件 四、使用llama-quantize 五、训练模型 六、将模型部署到ollama 一、将模型保存为gguf格式 在你的训练代码 trainer.train() 之后添加&#xff1a; model.save_pretrained_gguf(&q…...

Go语言中的值类型和引用类型特点

一、值类型 值类型的数据直接包含值&#xff0c;当它们被赋值给一个新的变量或者作为参数传递给函数时&#xff0c;实际上是创建了原值的一个副本。这意味着对新变量的修改不会影响原始变量的值。 Go中的值类型包括&#xff1a; 基础类型&#xff1a;int&#xff0c;float64…...

grafana新增email告警

选择一个面板 比如cpu 新增一个临界点表达式 input选A 就是A的值达到某个临界点 触发告警 我这边IS ABOVE0.15就是cpu大于0.15%就触发报警&#xff0c;这个值怎么填看指标的值显示 这里要设置一下报警条件 这边随便配置下 配置标签和通知&#xff0c;选择你的邮件 看下告警…...

基于Spring Security 6的OAuth2 系列之六 - 授权服务器--自定义授权页面

之所以想写这一系列&#xff0c;是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器&#xff0c;但当时基于spring-boot 2.3.x&#xff0c;其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0&#xff0c;结果一看Spring Security也升级…...

MyBatis-Plus的插件

一、分页插件 1.自带的 启动类 在启动类里配置分页相关内容 package com.qcby;import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inne…...

基于Redis实现短信验证码登录

目录 1 基于Session实现短信验证码登录 2 配置登录拦截器 3 配置完拦截器还需将自定义拦截器添加到SpringMVC的拦截器列表中 才能生效 4 Session集群共享问题 5 基于Redis实现短信验证码登录 6 Hash 结构与 String 结构类型的比较 7 Redis替代Session需要考虑的问题 8 …...

HarmonyOS Next构建工具 lycium 原理介绍

HarmonyOS Next构建工具 lycium 原理介绍 背景介绍 HarmonyOS Next中很多系统API是以C接口提供&#xff0c;如果要使用C接口&#xff0c;必须要使用NAPI在ArkTS与C间交互&#xff0c;这种场景在使用DevEco-Studio中集成的交叉编译工具&#xff0c;以及cmake构建工具就完全够用…...