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

news2025/1/24 21:05:45

一.五层(四层)模型

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。

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

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

相关文章

头像生成小程序搭建(免费分享)

如下图为小程序页面的基本效果&#xff0c;下面将介绍该小程序的功能 页面template代码如下&#xff1a; <template><view class"avatar-containner"><block v-if"!showCropper"><image class"pageback" src"../../s…

Unity自学之旅05

Unity自学之旅05 Unity学习之旅⑤&#x1f4dd; AI基础与敌人行为&#x1f94a; AI导航理论知识&#xff08;基础&#xff09;开始实践 &#x1f383; 敌人游戏机制追踪玩家攻击玩家子弹碰撞完善游戏失败条件 &#x1f917; 总结归纳 Unity学习之旅⑤ &#x1f4dd; AI基础与敌…

【分布式日志篇】从工具选型到实战部署:全面解析日志采集与管理路径

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

电子应用设计方案102:智能家庭AI鱼缸系统设计

智能家庭 AI 鱼缸系统设计 一、引言 智能家庭 AI 鱼缸系统旨在为鱼类提供一个健康、舒适的生活环境&#xff0c;同时为用户提供便捷的管理和观赏体验。 二、系统概述 1. 系统目标 - 自动维持水质稳定&#xff0c;包括水温、酸碱度、硬度和溶氧量等关键指标。 - 智能投食&…

【安当产品应用案例100集】034-安当KSP支持密评中存储数据的机密性和完整性

安当KSP是一套获得国密证书的专业的密钥管理系统。KSP的系统功能扩展图示如下&#xff1a; 我们知道商用密码应用安全性评估中&#xff0c;需要确保存储的数据不被篡改、删除或者破坏&#xff0c;必须采用合适的安全方案来确保存储数据的机密性和完整性。KSP能否满足这个需求呢…

linux系统下的磁盘扩容

背景&#xff1a;之前通过虚拟机装linux时硬盘空间设置的不够用&#xff0c;所以需要再加点容量。 1、首先通过虚拟机来扩展硬盘 注意&#xff1a;需要关闭linux系统&#xff1b;需要删除之前的快照&#xff1b; 我原来为27G&#xff0c;现在增加到了40G&#xff0c;如下图: …

【MySQL】 库的操作

欢迎拜访&#xff1a;雾里看山-CSDN博客 本篇主题&#xff1a;【MySQL】 库的操作 发布时间&#xff1a;2025.1.23 隶属专栏&#xff1a;MySQL 目录 库的创建语法使用 编码规则认识编码集查看数据库默认的编码集和校验集查看数据库支持的编码集和校验集指定编码创建数据库验证不…

fpga学习入门 串口rs232回环

奇偶检验位这里是省略了 做好回环后可以使用上位机做回环测试&#xff0c;top文件写的方式就是将rx&#xff08;fpga端&#xff09;接受到的模块&#xff08;pc端&#xff09;tx发送出去&#xff0c;这两个端口用杜邦线连接&#xff0c;同理模块的rx连接fpga的tx&#xff0c;…

认识Django项目模版文件——Django学习日志(二)

1.默认文件介绍 └── djangoproject1/├── djangoproject1/│ ├── urls.py [URL和函数的对应关系]【常用文件】│ ├── settings.py [项目配置文件]【常用文件】│ ├── _init_.py│ ├── wsgi.py [接受网络请求] 【不要动】│ └──…

微信小程序中常见的 跳转方式 及其特点的表格总结(wx.navigateTo 适合需要返回上一页的场景)

文章目录 详细说明总结wx.navigateTo 的特点为什么 wx.navigateTo 最常用&#xff1f;其他跳转方式的使用频率总结 以下是微信小程序中常见的跳转方式及其特点的表格总结&#xff1a; 跳转方式API 方法特点适用场景wx.navigateTowx.navigateTo({ url: 路径 })保留当前页面&…

postgresql15的启动

PostgreSQL是一个功能非常强大的、源代码开放的客户/服务器关系型数据库管理系统&#xff0c;且因为许可证的灵活&#xff0c;任何人都可以以任何目的免费使用、修改和分发PostgreSQL。现在国产数据库大力发展阶段&#xff0c;学习和熟悉postgresql的功能是非常有必要的&#x…

ChatGPT结合Excel辅助学术数据分析详细步骤分享!

目录 一.Excel在学术论文中的作用✔ 二.Excel的提示词✔ 三. 编写 Excel 命令 四. 编写宏 五. 执行复杂的任务 六. 将 ChatGPT 变成有用的 Excel 助手 一.Excel在学术论文中的作用✔ Excel作为一种广泛使用的电子表格软件&#xff0c;在学术论文中可以发挥多种重要作用&a…

大模型 / 智能体在智能运维领域的应用总结与发展趋势概述

智能体 智能运维 &#xff1f; 回顾大模型的发展 大模型的发展在过去两年间呈现出爆炸式的增长&#xff0c;成为推动人工智能领域快速进步的关键力量。 2023年3月&#xff1a;百度发布了其知识增强的大语言模型产品“文心一言”&#xff0c;这标志着国内AI大模型产业竞争的…

戴尔电脑设置u盘启动_戴尔电脑设置u盘启动多种方法

最近有很多网友问&#xff0c;戴尔台式机怎么设置u盘启动&#xff0c;特别是近两年的戴尔台式机比较复杂&#xff0c;有些网友不知道怎么设置&#xff0c;其实设置u盘启动有两种方法&#xff0c;下面小编教大家戴尔电脑设置u盘启动方法。 戴尔电脑设置u盘启动方法一、戴尔进入b…

【博客之星】年度总结:在云影与墨香中探寻成长的足迹

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、年度回顾 1、创作历程 2、个人成长 3、个人生活与博客事业 二、技术总结 1、赛道选择 2、技术工具 3、实战项目 三、前景与展望 1、云原生未来…

《安富莱嵌入式周报》第349期:VSCode正式支持Matlab调试,DIY录音室级麦克风,开源流体吊坠,物联网在军工领域的应用,Unicode字符压缩解压

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; 《安富莱嵌入式周报》第349期&#xff1a;VSCode正式支持Matlab调试&#xff0c;DIY录音室级麦克风…

cursor ide配置远程ssh qt c++开发环境过程记录

cursor是啥就不介绍了&#xff0c;好像是目前最好用的ai ide&#xff0c;下面主要是配置远程ssh连接linux机器进行qt5 c程序运行的配置过程记录。 一、c_cpp_properties.json 在项目根目录的.vscode目录里面新建c_cpp_properties.json文件&#xff0c;根据你的实际情况配置该文…

Langchain+文心一言调用

import osfrom langchain_community.llms import QianfanLLMEndpointos.environ["QIANFAN_AK"] "" os.environ["QIANFAN_SK"] ""llm_wenxin QianfanLLMEndpoint()res llm_wenxin.invoke("中国国庆日是哪一天?") print(…

lwIP——3 内存管理

目录 1.什么是内存管理 2.lwIP内存堆 3.lwIP内存堆程序代码解析 3.1 mem_init程序解析 3.2 mem_malloc程序解析 3.3 mem_free程序解析 4.lwIP内存池 5.lwIP内存池程序代码解析 5.1 实现lwIP内存池的文件 5.1.1 memp_priv.h 5.1.2 memp_std.h 5.1.3 memp.h memp_t 枚…

使用 Serilog 在 .NET Core 6.0 中日志记录

在本文中&#xff0c;我们将讨论日志记录的基础知识以及在 .NET Core 6 中使用 Serilog 的逐步实现。 先决条件 1、Visual Studio 2022。 2、C# 和 .NET Core 的基础知识。 3、.NET Core 6 SDK。 日志记录基础知识 从技术角度来说&#xff0c;日志记录是记录事件并捕获应用程…