浅谈网络通信(1)

文章目录

  • 一、认识一些网络基础概念
    • 1.1、ip地址
    • 1.2、端口号
    • 1.3、协议
    • 1.4、协议分层
    • 1.5、协议分层的2种方式
      • 1.5.1、OSI七层模型
      • 1.5.2、TCP/IP五层模型[!]
        • 1.5.2.1、TCP/IP五层协议各层的含义及功能
  • 二、网络中数据传输的基本流程——封装、分用
    • 2.1、封装
    • 2.2、分用
      • 2.2.1、5元组
  • 三、进行网络编程
    • 3.1、UDP
      • 3.1.1、UDP 的特点
    • 3.2、TCP
      • 3.2.1、TCP 的特点
    • 3.3 TCP、UDP特点解析
    • 3.4、使用传输层协议 TCP/UDP 提供的 socket api 进行网络通信
      • 3.4.1、UDP—— DatagramSocket、DatagramPacket
        • 3.4.1.1 使用UDP协议编写回显服务器

一、认识一些网络基础概念

1.1、ip地址

使用 ip 地址,来描述网络上一个设备所在的位置。

1.2、端口号

区分一个主机上不同的应用程序。
一个网络程序,在启动时,都需要绑定一个或多个端口号,因为后续的通信都需要依赖端口来展开。

1.3、协议

协议描述了网络通信时传输的数据的含义。

1.4、协议分层

协议就只是表示一种约定,这样的约定可以是任意的,由于网络通信协议是复杂的,因此在经过了多年的发展后,行业标准、专家已经规定出了现成的协议,我们只需要学习好规定出的现成协议即可。

那为什么要约定好这么一份通用的协议呢?

这是由于在网络通信中,电脑种类很多,制作设备的厂商也很多,必须有一份统一的协议标准,让大家都按照同样的标准研发设备,以确保不同的厂商研发出的东西都能够在一起相互通信。

但由于网络通信确实是十分复杂的,故会涉及到一系列非常繁琐、细节的工作,因此仅靠一个协议就解决所有问题,就导致这个协议就会十分庞大、复杂,因此此时就需要对协议进行分层。

上层协议 调用 下层协议,下层协议 给 上层协议提供服务。

例子:
在这里插入图片描述
协议也是如此。

1.5、协议分层的2种方式

1.5.1、OSI七层模型

OSI七层模型一般只存在于教科书中。
在这里插入图片描述

1.5.2、TCP/IP五层模型[!]

TCP/IP五层模型是如今网络通信最常用的模型,很重要!
在这里插入图片描述

1.5.2.1、TCP/IP五层协议各层的含义及功能

第一层:物理层
含义: 负责在物理媒介上发送和接收原始比特流。
功能: 为网络通信提供物理连接,定义了如网卡、网口、网线等物理设备的标准。
第二层:数据链路层
含义: 为相邻节点提供端到端的直接链接服务,以帧的形式传输数据。
功能: 错误检测和修正,管理帧数据。
第三层:网络层
含义: 负责数据在网络中的路由选择和转发,确保数据从源 ip 地址传送到 目的 ip 地址。
功能: 路由选择,数据包的封装与分用。
第四层:传输层
含义:直接提供端到端的服务,只关注起点和终点,不关注中间的实现过程。
功能: 对端口号进行管理
第五层:应用层
含义: 为应用程序提供网络通信服务。
功能: 允许应用程序与网络交互,实现数据传输、文件共享、电子邮件…等网络通信功能。

在这里插入图片描述
举个例子加深对TCP/IP五层模型中各层的理解:
1、物理层 :约定网络通信中的一些基础设施需要遵守的规范,如约定这些信息:网线、网口、网口… 就像快递车行驶在公路上运送快递时,公路、信号灯、公路上的绿化形式…都有一定的制定标准。
2、数据链路层 :相邻节点之间,数据是如何传输的。快递公司运送快递时,确定好快递的运输路线之后,假设此时快递车运送快递的路线是:广东——>柳州——>南宁,那么此时就需要考虑该条路线中的相邻节点之间是怎么走的,如从广东——>柳州,快递是怎么运送的,到底是水运、还是航运…,而从柳州——>南宁,快递是怎么运送的,到底是陆运、还是航运…
3、网络层 :与路径规划有关。j就像当前快递车运送快递的路线是怎么规划的:俗话说,条条大路通罗马,因此运送快递到达目的地其实可以有很多条不同的路线能够到达目的地。譬如说有,广东——>柳州——>南宁、广东——>桂林——>南宁…究竟选择哪条路线运送快递,由网络层负责。
4、传输层:只关注起点和终点,不关注中间过程。譬如网购时,需要告知卖家自己的收件地址,那此时卖家去快递公司寄快递给用户时,就会告知快递公司当前所寄商品是从哪里寄出,要寄往哪里,此时就行了,至于快递公司将此快递从哪里运输到哪里,怎么打包、运输、运输的过程产生的油费、运输的路径规划…都不需要我们关心,是由快递公司负责,我们只需要在规定时间内能收到自己的快递即可。
5、应用层:拿到这个数据之后我们要干什么。即获取到数据之后是要进行文件传输、邮件发送、还是…其他的,是由应用层说了算的。

对于我们程序员来说,我们和传输层、应用层打的交道比较多,因此必须重点掌握传输层、应用层的含义、功能、api、使用。

二、网络中数据传输的基本流程——封装、分用

2.1、封装

以QQ发送消息为例子:主机A发送消息给主机B,介绍网络中传输数据的基本流程。

主机A的情况:

1、应用层:

QQ应用程序,从输入框中获取到我们要传送的数据,根据应用层协议,构造成应用层数据报,应用层含有很多现成的协议,但很多应用程序中会自定义应用层协议,那么QQ自定义的应用层协议是啥样的?咱们不知道,只有开发者才知道,因此此处QQ自定义的应用层协议我们通过假设进行举例子。

假设QQ的应用层协议是这样自定义的:
发件人的QQ号、接收人的QQ号、时间、消息内容

那么此时就需要将自定义好的应用层协议,构造成应用层数据报构造应用层数据报的过程,就是按照一定格式进行字符串拼接
在这里插入图片描述

发送方和接收方需要达成一致,发送方使用什么样的应用层协议进行发送数据,接受方就要使用什么样的应用层协议接收数据。

应用程序自定义的好应用层协议后,并且构造好应用层数据报后,就会调用传输层提供的接口,把应用层数据报(携带了应用程序所想发送的消息)交给传输层进行处理

2、传输层:
传输层的现成协议很多,最常用的就是 TCP 协议、UDP 协议,此处假设使用 UDP 协议处理应用层传过来的的数据报。

UDP 协议就会按照自己的协议格式,生成一个 UDP 数据报:该 UDP 数据报,会将应用层数据报作为自己的载荷部分,并且在载荷部分的前面添加一个 UDP 报头。

在这里插入图片描述
UDP 协议不关心应用层数据报里含有什么数据,是什么内容,只是把应用层数据报当作一个字符串,再构造出一个传输层数据报。

就像发快递一样,假设你想寄的快递是衣服,你拿到快递站之后,交给快递员,快递员会把你的衣服包装成一个包裹,然后在上面贴上快递单,此时你要寄的衣服(相当于应用层数据报)就已经变了一个样子,变成了一个快递包裹件,上面有快递单(此时这个贴了快递单的包裹,就相当于 UDP 数据报)。只要你邮寄的东西,不管是衣服、还是其他的,只要不违禁,快递是不会关心你要寄什么东西的,他只负责给你包装,然后贴单子(这个单子上面就含有快递的发件人、收件人…这里的发件人、收件人就相当于一个 源端口、目的端口),发出去。

3、网络层:
网络层中也含有众多现成的网络层协议,最主要的协议的是 IP 协议。 IP协议会根据从传输层中收到的 UDP 数据报,构造出 IP 数据报,IP数报中就包含 源IP地址 和 目的IP地址,来确保数据能够从 源IP地址 正确传输到 目的IP 地址。

在这里插入图片描述
就像我们发快递一样,在快递上贴的快递单上的发件人地址和收件人地址,就相当于 源IP地址 和 目的IP地址,都是为了确保正确传输。

4、数据链路层:
数据链路层也提供了许多现成的协议,最主要的是 以太网 协议,以太网,又会针对网络层传输来的数据报进行封装,为IP数据报添上帧头、帧尾。

以太网也不关心载荷里是啥,只是把载荷当作字符串,进一步的拼接上帧头、帧尾,构造成以太网数据帧,然后进一步再将以数据链路层数据报发送给物理层。
在这里插入图片描述

5、物理层:
物理层是硬件设备(如网卡),硬件设备需要将上述数据进行转换,将拼接好的字符串数据转成二进制数据,通过光信号/电信号/电磁波传输。

此时,将数据进行了多层封装,最终将信号转成了光信号,在网络中进行传输,主机A就完成了发送过程。

2.2、分用

主机B的情况。

1、物理层:
硬件设备(网卡),收到网络方传输来的光信号/电信号/电磁波,那此时就需要通过调制解调器(猫),针对光信号进行调制解调。

调制:把你要传输的信息放到光电信号中。
解调:从光电信号中把信息取出来。

那此时,物理层就通过调制解调器器,将光电信号中的数据取出来,即:以太网的数据帧,这个数据就要被交给上一层,数据链路层。

在这里插入图片描述

2、数据链路层
数据链路层的以太网协议,就会针对这个数据进行解析,即:将以太网数据帧的帧头、帧尾去掉,取出其载荷部分,交给上层——网络层。
在这里插入图片描述

3、网络层:
IP协议针对这个数据进行解析:即去掉IP报头,取出载荷,进一步交给传输层。
在这里插入图片描述

4、传输层:
根据IP报头中的字段,就知道当前这个载荷是一个 UDP 数据报,故将此数据报交给 UDP 协议处理,此时UDP也要针对数据报进行解析,去掉报头。
在这里插入图片描述
5、应用层:
UDP报头中,有一个字段——>目的端口,根据目的端口找到关联的应用程序,然后将此应用层数据报交给这个程序即可,该程序会根据自定义的应用层协议解析该数据报,然后将数据显示到界面上。
在这里插入图片描述
此时,完成上述一系列分用步骤后,QQ中对应的头像就开始闪烁,点进去,就能显示出这个消息,以及消息的接收时间等信息…

主机A,从上到下,依次添加报头的过程,称为 “封装”,主机B,从下到上,依次解析报头的过程,称为 “分用”,每次网络传输,都需要经历这个过程。封装就像是在打包快递,分用,就像是在拆快递。

消息转发到某个设备,每个设备的处理流程都是和上面的封装分用是一致的。

如果消息转发到的设备是一个交换机,交换机封装分用到数据链路层即可:交换机解析出以太网数据帧,进一步获取到帧头中的 “mac”地址,根据 "mac"地址查询交换机内部的转发表,确定接下来数据从哪个网口发出去,在发送之前又会把以太网数据帧封装好。

如果消息转发到的设备是一个路由器,路由器封装分用到网络层即可:路由器解析出IP数据报,进一步获取到IP报头中的I目的P地址,根据目的IP地址进一步规划接下来要走的路线,然后在发送之前又会把IP数据报封装好。

2.2.1、5元组

使用 5元组 来描述一次网络通信:1、源 IP 地址 2、目的 IP 地址 3、源端口号 4、目的端口号。5、协议类型。

三、进行网络编程

写一个应用程序,这个应用程序可以使用网络通信,就需要依靠操作系统给传输层协议对外提供的api。传输层主要的协议有:TCP、UDP,这两个协议关于网络通信方面,提供了两套完全不同的 api。

传输层用于网络通信的 api 叫做 socket api。

3.1、UDP

3.1.1、UDP 的特点

1、无连接
2、不可靠传输
3、面向数据报
4、半双工

3.2、TCP

3.2.1、TCP 的特点

1、有连接
2、可靠传输
3、面向字节流
4、全双工

3.3 TCP、UDP特点解析

1、什么叫做 无连接?有连接?
譬如说我们在javase时学过的JDBC编程,JDBC是:先创建一个数据源 DataSource,再通过 DataSource 创建 Connection 连接,那么这就是一种 有连接,该连接是抽象的,连接是用来通信时保存对方信息的。

再譬如说,打电话。当我们打电话时,首先按下拨号键,直到对方接通为止,才算是完成连接,这也是一种有连接的表现。

那么客户端与服务器之间进行通信时,使用 内存(本本)保存对端的信息,双方都保存这个信息,此时 “连接” 就出现了,那么与JDBC的连接、打电话的连接不同的是,一个客户端可以连接多个服务器,一个服务器也可以对应多个客户端。

那么像QQ、微信进行发送消息时,是不需要建立连接的,就能直接发送消息进行通信,这是一种 无连接 的变现。

其实除了连接,还有一种叫做 链接 的情况,链接与连接不同,链接相当于一种快捷方式,即:通过一个文件,让该文件的内容保存另一个文件的路径,实现的链接,一般是软链接(软件的链接)。

2、什么叫 可靠传输?什么叫 不可靠传输?
可靠传输,不是说A给B发消息,100%能到,这个要求太难了,可靠传输,就是说,A给B发消息时,会尽可能地将消息传给B,并且传输失败的时候,A能感知到、或者在传输的时候,A能知道自己是否传输成功!

譬如说,对于应用程序:钉钉、飞书、企业微信…这些应用程序用到的就是可靠传输,即当用户A给用户B发消息时,用户A能够清楚地感知到用户B是否接收到消息,如果消息旁边出现 “已读”,那就说明用户B已经收到该消息并且查看了;如果消息旁边什么都没有出现,说明当前消息已经通过网络传输到给了用户B,但是用户B并没有点击查看该消息。

不可靠传输即:就像我们平常所用的QQ、微信…这些软件,当用户A给用户B发送了一条消息,无论用户是否点击查看了该条消息,该消息的是输入框旁边,都不会出现 “已读” 的提示,因此,用户A此时就无法判断当前消息的发送情况。

TCP的特点就是可靠传输,但是可靠传输的前提是TCP牺牲了传输效率,UDP的特点是不可靠传输,因此UDP的传输效率比TCP高,但是UDP并不能保证消息传输过程的可靠性,极易出现丢包、顺序颠倒、数据包重复的情况。

3、什么叫做 面向数据报?面向字节流?
面向数据报、面向字节流 这样的特点是跟代码的编写息息相关的,务必要重视的去掌握该知识点。对于 UDP 来说,其在网络中传输数据的基本单位是 数据报,那么一个UDP数据报的格式,是十分重要的,后续会介绍。而TCP在网络中传输数据的基本单位是 字节,就跟文件操作类似,都是 “流” 式的。譬如说,通过 TCP 读写 100字节数据,可以一次读写 100 字节,也可以分2次读写,分别读写50字节;也可以分10次读写,每次读写10字节。

[易错题]:TCP是可靠传输、UDP是不可靠传输,因此TCP比UDP更安全?这是正确的还是错误的?[错误的],谈到网络安全,指的是:你传输的数据是否容易被黑客截获,以及如果被截获之后是否会泄露一些重要信息,网络安全是和 安全、入侵、加密、反编译…有关,而不是和可靠传输与否有关。

4、什么叫做 全双工?半双工?
全双工:进行网络通信的通道可以双向传递数据。
半双工:进行网络通信的通道只能单向传递数据。

3.4、使用传输层协议 TCP/UDP 提供的 socket api 进行网络通信

3.4.1、UDP—— DatagramSocket、DatagramPacket

UDP提供两个不同的核心类进行网络通信:

一、DatagramSocket:

操作系统是使用 文件 这样的概念,来管理一些软硬件资源,我们使用一些硬件的网络设备进行网络通信时(网卡…),操作系统也是使用 文件 这样的方式管理网卡这样的硬件设备,而我们将表示网卡的这类文件,称为 socket 文件。

Java中的 socket 对象,就对应系统里的 socket 文件,最终落到网卡这样用于进行网络通信的硬件设备。

还有一些其他的硬件设备,譬如说:键盘、鼠标、显示器等硬件设备插入电脑上使用时,操作系统也是将这些硬件设备当作 一个一个的 文件 管理起来。

因此,如果我们程序员写的应用程序,想要进行网络通信,就必须在代码中先有 socket 对象。

那么,上述的 DatagramSocket 就是一个 socket 对象。

DatagramSocket 的构造方法:

1、DatagramSocket()
此构造方法是在客户端处使用,客户端想要进行网络通信,也是需要先有一个 socket 对象。客户端使用哪个端口,不需要客户端自己指定,而是由系统自动分配,这是因为客户端大部分是计算机小白,他们自己指定端口号,极易发生端口冲突,造成网络通信失败。

2、DatagramSocket(int port)
此构造方法是在服务器端使用的,服务器端需要自己指定端口号,以便客户端能够找到当前服务器来进行网络通信。那为什么服务器端又能够进行手动指定端口号??此时不怕端口冲突了??这是因为对于服务器端来说,服务器端是由程序员掌控的,因此此时程序员对于服务器上的应用程序的端口号分配情况了如指掌,因此此时指定的端口号是经过考察才分配的,此时就不会造成端口冲突,以至于网络通信失败这样的情况发生了。

当客户端给服务器发送消息时,对于客户端来说,客户端的端口号是源端口号,服务器的端口号是目的端口号;当服务器给客户端发消息时,对于服务器来说,服务器的端口号是源端口号,客户端的端口号是目的端口号。

举个例子理解端口号在网络通信中的重要作用:
有一天,我去城中街道58号餐厅吃饭。那么这个地址:城中街道58号 就唯一标识了一条街道上的某一家餐厅,因为一个城市,会有许多条街道,一条街道上,会有许许多多的餐馆(那么对于一个服务器端来说,一个服务器上,也会有许多应用程序)。此时的 城中街道 就相当于服务器的 IP地址,58号 就相当于 服务器的端口号,而慕名而来吃饭的客人,就相当于客户端,假如我第一次到这个餐厅里,坐的位置是10号桌,那么下一次来这个餐厅,坐的还是10号桌吗??不一定了,这个位置是随机分配的。因此此时 10号 桌 就相当于 客户端的端口号,不需要客户端自己指定,而是由系统自动分配即可。

3、DatagramSocket 中提供的用于网络通信的方法:

1)、void receive(DatagramPacket p)
使用该方法读取请求并解析,该方法的参数是一个 数据报,**因为 UDP 协议在网络传输数据的基本单位的 数据报。

2)、void send( DatagramPacket p)
使用该方法发送一个数据报,该方法的参数也是一个 数据报。

3)、void close()
通过该方法,关闭 socket 文件,防止出现 文件资源泄露 问题。

二、DatagramPacket

DatagramPacket 表示一个 数据报。

DatagramPacket 的构造方法:

1、DatagramPacket(byte[] buf,int length)
该构造方法代表了系统中设定的 UDP 数据报的二进制结构。该构造方法使用 byte数组来接受数据,因为 DatagramPacket 作为 UDP 数据报,必然要能够承载一些数据,我们需要通过手动指定 byte[] 作为数据存储的空间。

2、DatagramPacket(byte[] buf,intt length,SocketAddress address)
该构造方法一般用于发送数据,参数有 byte 数组,用来为发送的数据作承载空间,length表示数据的实际长度,address表示IP地址以及端口号。

3.4.1.1 使用UDP协议编写回显服务器

回显服务器:客户端发什么、服务器就返回什么。

服务器端代码:

package UDP.network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.concurrent.ExecutorService;//回显服务器
public class UDPEchoServer {private DatagramSocket socket = null;ExecutorService executorService = null;
//    参数是:服务器的端口号,客户端通过这个服务器的端口号与服务器进行网络通信public UDPEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}//    启动服务器public void start() throws IOException {
//        通过 while 循环反复处理 不知道何时与服务器进行通信的 众多客户端System.out.println("[UDPEchoServer] 服务器启动!");while (true){//            服务器做的3步:
//            1、读取请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);try {socket.receive(requestPacket);} catch (IOException e) {e.printStackTrace();}
//            通过 getData() 获取数据报中的数据String request = new String(requestPacket.getData(),0,requestPacket.getLength());
//            2、根据请求计算出响应   通过 process() 方法,完成根据请求计算出响应,这一步是最复杂最关键的,不同的服务器不同的功能,就是这一步不同String response = process(request);
//            3、返回响应   requestPacket.getSocketAddress():通过这个获取到客户端的ip地址以及端口号,这样就可以将响应返回给特定的客户端DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());try {socket.send(responsePacket);} catch (IOException e) {e.printStackTrace();}
//            打印日志信息System.out.printf("[%s:%d] req:%s,resp:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UDPEchoServer server = new UDPEchoServer(8909);server.start();}
}

客户端代码:

package UDP.network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;//客户端
public class UDPEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;//    服务器的ip地址,端口号public UDPEchoClient(String ip,int port) throws SocketException {serverIp = ip;serverPort = port;socket = new DatagramSocket();}public void start() throws IOException {System.out.println("[UDPEchoClient] 客户端启动!");while (true){
//            从控制台输入用户信息System.out.println("请输入信息:-> ");Scanner sc = new Scanner(System.in);String request = sc.next();//            再将用户输入的信息构造成一个UDP数据报,发送给服务器处理DatagramPacket requestPacket =  new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);
//            发送请求socket.send(requestPacket);//            读取服务器的响应,并解析出响应内容DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(),0,responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UDPEchoClient client = new UDPEchoClient("127.0.0.1",8909);
//        UDPEchoClient client = new UDPEchoClient("42.192.83.143",9090);client.start();}
}

端口号,是用来区分主机上不同的应用程序,**一个应用程序可以占据主机上的多个端口号,一个端口只能被一个进程占有(**其实是有特例的,但是一般情况下是在这样的)。如果应用程序在网络通信中出现通信异常:SocketException ,一般都是因为当前端口号已经被别的进程占用,此时再尝试创建这个 socket 对象,占用该端口,就会报错——编写网络通信代码时,此类异常会很常见!

解析使用UDP编写回显服务器代码:
在这里插入图片描述
在服务器端的 start() 方法中,使用 while循环来等待并循环处理客户端的请求,因为一个服务器需要给很多的客户端提供服务,服务器不知道客户端什么时候来,服务器只能 “时刻准备着”处理客户端的请求。

而 socket.receive() 方法中,参数是DatagramPacket,是一个 “输出型参数”,传入 receive 的是一个空的 DatagramPacket 对象,receive() 内部会将这个空的 DatagramPacket 对象的内容填充上,当 receive() 执行结束之后,就会得到一个 装满内容的 DatagramPacket。

对于 response.getBytes().length 和 response.length()来说,这两者有什么区别??这很重要,一定不要弄错。如果当 response 里都是英文字母时,这两者获取到的长度是一样的,但是如果说 response 里是2个汉字时,此时这两者获取到的长度就会有差别,一个汉字是3个字节,response.length()此时获取到的长度是2,而 response.getBytes().length 获取到的长度是 6。 Socket api 本身,是按照字节来处理数据的。

对于 requestPacket.getSocketAddress() 来说,是用来获取IP地址和端口号的,DatagramPacket 这个对象里就包含了通信双方的 IP地址和端口号。

socket对象 就相当于一个 socket 文件,因此 socket 对象用完后,就需要及时关闭,以免造成文件资源泄露问题,导致程序异常。那么此时 socket = new DatagramSocket(port); 来说,是否需要关闭呢??

对于我们当前编写的这个服务器程序来说,DatagramSocket 不关闭,也是可以的。因为整个程序中,只有这么一个 socket 对象,且不是在频繁创建的情况下。这个 socket 对象生命周期十分长,伴随整个程序,此时,socket 就需要保持打开的状态。

socket 对象 ——>系统中的 socket 文件——>文件描述符(文件描述符即表示当前进程所占有的文件,进程每打开一个文件,就会生成一个文件描述符)(关闭 socket 对象的主要原因,就是因为要释放文件描述符),但是因为我们此时程序中只有一个 socket 对象,且生命周期伴随整个程序,此时无需手动关闭,只需要等待进程结束后,系统将PCB回收后,PCB里的文件描述符表字段也就被销毁了。

仅限于,只有一个 socket 对象,并且生命周期是跟随整个进程。如果是含有多个 socket 对象,并且 socket 对象的生命周期短,需要频繁创建、释放,就必须去关闭 socket!

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

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

相关文章

【保姆级介绍下Foxmail 邮箱】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

C++-指针

在C中,指针是至关重要的组成部分。它是C语言最强大的功能之一,也是最棘手的功能之一。 指针具有强大的能力,其本质是协助程序员完成内存的直接操纵。 指针:特定类型数据在内存中的存储地址,即内存地址。 指针变量的定…

大模型时代的具身智能系列专题(五)

stanford宋舒然团队 宋舒然是斯坦福大学的助理教授。在此之前,他曾是哥伦比亚大学的助理教授,是Columbia Artificial Intelligence and Robotics Lab的负责人。他的研究聚焦于计算机视觉和机器人技术。本科毕业于香港科技大学。 主题相关作品 diffusio…

kafka-消费者组偏移量重置

文章目录 1、消费者组偏移量重置1.1、列出所有的消费者组1.2、查看 my_group1 组的详细信息1.3、获取 kafka-consumer-groups.sh 的帮助信息1.4、 偏移量重置1.5、再次查看 my_group1 组的详细信息 1、消费者组偏移量重置 1.1、列出所有的消费者组 [rootlocalhost ~]# kafka-…

高性价比、超强功能的开源工单解决方案

在企业日常运营中,工单管理系统是不可或缺的工具。高效的工单管理不仅能提升工作效率,还能显著提高客户满意度。今天,我们为您推荐搭贝工单派单系统——一款超高性价比、功能齐全的开源工单管理系统。 🔍 为什么选择搭贝工单派单…

docker占用磁盘空间大小排查

首先进入到 /var/lib/docker/overlay2 目录下,查看谁占用的较多 cd /var/lib/docker/overlay2/du -s ./* | sort -rn | more再通过目录名查找容器名 docker ps -q | xargs docker inspect --format {{.State.Pid}}, {{.Id}}, {{.Name}}, {{.GraphDriver.Data.WorkDir}} | gre…

11.RedHat认证-Linux文件系统(中)

11.RedHat认证-Linux文件系统(中) Linux的文件系统 格式化分区(1道题) #对于Linux分区来说,只有格式化之后才能使用,不格式化是无法使用的。 #Linux分区格式化之后就会变成文件系统,格式化的过程相当于对分区做了一个文件系统。 #Linux常见…

【Linux 网络编程】网络的基础知识详解!

文章目录 1. 计算机网络背景2. 认识 "协议"3. 协议分层 1. 计算机网络背景 网络互联: 多台计算机连接在一起, 完成数据共享; 🍎局域网(LAN----Local Area Network): 计算机数量更多了, 通过交换机和路由器连接。 🍎 广…

slam14讲(第9,10讲 后端)

slam14讲(第9,10讲 后端) 后端分类基于滤波器的后端线性系统和卡尔曼滤波非线性系统和扩展卡尔曼滤波 BA优化H矩阵的稀疏性和边缘化H矩阵求解的总结 位姿图优化公式推导 基于滑动窗口的后端个人见解旧关键帧的边缘化 后端分类 基于滤波器的后…

Hadoop3:MapReduce之简介、WordCount案例源码阅读、简单功能开发

一、概念 MapReduce是一个 分布式运算程序 的编程框架,是用户开发“基于 Hadoop的数据分析 应用”的核心框架。 MapReduce核心功能是将 用户编写的业务逻辑代码 和 自带默认组件 整合成一个完整的 分布式运算程序 ,并发运行在一个 Hadoop集群上。 1、M…

3DEXPERIENCE DELMIA Role: RVN - Robotics Virtual Commissioning Analyst

Discipline: Robotics Role: RVN - Robotics Virtual Commissioning Analyst 通过准确地模拟连接到PLC程序的机器人、设备和传感器,在制造虚拟孪生上执行虚拟调试情景 为任何机器人角色的多周期情景创建传感器,生成和变换零件启用 PLC 程序的虚拟验证和…

【ai】livekit:Agents 4: livekit-plugins-openai和LiveKit Plugins Silero安装与分析

先提高下性能然后本文 继续按照 上一篇【ai】livekit:Agents 3 : pythonsdk和livekit-agent的可编辑模式下的安装构建 livekit-gent的插件。pycharm 工程 配置Microsoft Defender 排除列表 livekit-plugins-openai 本地安装

【JS基础知识07】函数

一:函数是什么以及函数作用 1 函数是什么 函数是经过封装、调用后,能够完成特定任务的代码块 2 函数的作用 仅需“函数名(实参)”就可以调用函数,起到精简代码,提高开发效率的作用 二:函数使用 1 语法规则&#…

一款免费的软件媒体系统软件!!【送源码】

Jellyfin是一个免费的软件媒体系统,让您在管理和流媒体控制您的媒体。它是专有的Emby和Plex的替代品,通过多个应用程序从专用服务器向最终用户设备提供媒体。Jellvfin是Emby的3.5.2版本的后裔,并被移植到.NETCore框架中,以实现完全…

SpringBootWeb 篇-深入了解会话技术与会话跟踪三种技术(Cookie 会话跟踪、Session 会话跟踪与 JWT 令牌会话跟踪)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 会话技术 2.0 会话跟踪 2.1 会话跟踪 - Cookie 2.1.1 客户端获取 Cookie 的流程 2.1.2 Cookie 会话跟踪的特点 2.2 会话跟踪 - Session 2.2.1 客户端获取 SESSION…

Let‘s Encrypt 免费证书申请

填写邮箱,申请的域名 单域名:www.example.com 泛域名: *.example.com yum -y install certbot sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns --email xxexample…

AI 驱动的低代码平台-网易CodeWave 低代码平台 AI 智能化实践

一、实践背景: 随着低代码赛道的蓬勃发展,越来越多的低代码产品如雨后般春笋涌出开始进入市场,面对市场的考验,低代码平台也在面临两大问题: 定制开发的使用门槛太高,效率太低。低代码产品进入到企业当中…

ArcGIS不同图斑设置不同的透明度

对于设置一个图层的整体的透明度,我们在 ArcGIS制作带蒙版的遥感影像地图http://mp.weixin.qq.com/s?__bizMzIzNjM2NTYxMg&mid2247509080&idx1&sn38dccf0a52bb3bb3758f57114ee38b72&chksme8da161bdfad9f0d363da90959a8524dcf2b60d0e8d999f8ebeef0…

操作系统真象还原:编写MBR主引导记录,让我们开始掌权

第2章-编写MBR主引导记录,让我们开始掌权 这是一个网站有所有小节的代码实现,同时也包含了Bochs等文件 在开机的一瞬间,也就是接电的一瞬间, CPU 的 CS: ip 寄存器被强制初始化为 0XF000: 0XFFF0。由于开机的时候处于实模式&…

橙派探险记:开箱香橙派 AIpro 与疲劳驾驶检测的奇幻之旅

目录 引子:神秘包裹的到来 第一章:香橙派AIpro初体验 资源与性能介绍 系统烧录 Linux 镜像(TF 卡) 调试模式 登录模式 第二章:大胆的项目构想 系统架构设计 香橙派 AIpro 在项目中的重要作用 第三章&#xf…