| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 网络笔记--协议栈和网卡 -> 正文阅读 |
|
[网络协议]网络笔记--协议栈和网卡 |
? ? ? ? 这一节了解一下协议栈和网卡,主要是一些概念的介绍。操作系统中的协议栈是如何处理数据发送请求的?简单分如下几大步骤:?(1) 创建套接字(2) 连接服务器(3) 收发数据(4) 从服务器断开连接并删除套接字(5) IP 与以太网的包收发操作(6) 用 UDP 协议收发数据的操作。 ? ? ?TCPIP分层:浏览器、 邮件等一般应用程序收发数据时用 TCP;DNS 查询等收发较短的控制数据时用UDP。 ? ? ?网络包: 网络中的数据会被切分成几十字节到几千字节的小块, 每一个小数据块被称为一个 ? ??套接字的实体就是通信控制信息:?在协议栈内部有一块用于存放控制信息的内存空间, 这里记录了用于控制通信操作的控制信息, 例如通信对象的 IP 地址、 端口号、 通信操作的进行状态等。 本来套接字就只是一个概念而已, 并不存在实体, 如果一定要赋予它一个实体, 我们可以说这些控制信息就是套接字的实体,或者说存放控制信息的内存空间就是套接字的实体。 ? ? ? ? 协议栈在执行操作时需要参阅这些控制信息 ,?例如在发送数据时,需要看一看套接字中的通信对象 IP 地址和端口号, 以便向指定的 IP 地址和端口发送数据。 在发送数据之后, 协议栈需要等待对方返回收到数据的响应信息, 但数据也可能在中途丢失, 永远也等不到对方的响应。在这样的情况下, 我们不能一直等下去, 需要在等待一定时间之后重新发送丢失的数据, 这就需要协议栈能够知道执行发送数据操作后过了多长时间。 为此, 套接字中必须要记录是否已经收到响应, 以及发送数据后经过了多长时间, 才能根据这些信息按照需要执行重发操作。 ? ? ? ?套接字中记录了用于控制通信操作的各种控制信息, 协议栈则需要根据这些信息判断下一步的行动, 这就是套接字的作用。? 协议栈是根据套接字中记录的控制信息来工作的。 ? ? ?调用 socket 时的操作:看一下浏览器通过 Socket 库向协议栈发出委托的一系 连接服务器 连接:创建套接字之后, 应用程序(浏览器) 就会调用 connect, 随后协议栈会将本地的套接字与服务器的套接字进行连接。服务器这边又是怎样的情况呢? 服务器上也会创建套接字 ?服务器需要让客户端向服务器告知必要的信息, 比如“我想和你开始通信, 我的 IP 地址是 xxx.xxx.xxx.xxx, 端口号是 yyyy。连接实际上是通信双方交换控制信息, 在套接字中记录这些必要信息并准备数据收发的一连串操作, 像上面提到的客户端将 IP地址和端口号告知服务器这样的过程就属于交换控制信息的一个具体的例子。 ? ? ?控制信息, 就是用来控制数据收发操作所需的一些信息, IP地址和端口号就是典型的例子。 ? ? ? 通信操作中使用的控制信息分为两类:(1) 头部中记录的信息(2) 套接字(协议栈中的内存空间) 中记录的信息? ? ? ? 连接操作的实际过程?:?这个过程是从应用程序调用 Socket 库的 connect 开始, connect(< 描述符 >, < 服务器 IP 地址和端口号 >, …),上面的调用提供了服务器的 IP 地址和端口号, 这些信息会传递给协议栈中的 TCP 模块。 然后, TCP 模块会与该 IP 地址对应的对象, 也就是与服务器的 TCP 模块交换控制信息, 这一交互过程包括下面几个步骤。1 客户端先创建一个包含表示开始数据收发操作的控制信息的头部。头部包含很多字段,主要是发送方和接收方的端口号。 ?这样客户端(发送方) 的套接字就准确找到服务器(接收方) 的套接字, 也就是搞清楚了我应该连接哪个套接字。2 将头部中的控制位的 SYN 比特设置为 1它表示连接。总结:连接操作的第一步是在 TCP 模块处创建表示连接控制信息的头部。通过 TCP 头部中的发送方和接收方端口号可以找到要连接的套接字。 ? ? ? ? ?当 TCP 头部创建好之后, 接下来 TCP 模块会将信息传递给 IP 模块并委托它进行发送IP 模块执行网络包发送操作后, 网络包就会通过网络到达服务器, 然后服务器上的 IP 模块会将接收到的数据传递给 TCP模块, 服务器的 TCP 模块根据 TCP 头部中的信息找到端口号对应的套接字, 也就是说, 从处于等待连接状态的套接字中找到与 TCP 头部中记录的端口号相同的套接字就可以了。 当找到对应的套接字之后, 套接字中会写入相应的信息, 并将状态改为正在连接 。 上述操作完成后, 服务器的 TCP 模块会返回响应,这个过程和客户端一样, 需要在TCP 头部中设置发送方和接收方端口号以及 SYN 比特。此外, 在返回响应时还需要将 ACK 控制位设为 1,这表示已经接收到相应的网络包。设置 ACK 比特主要是用来确认双方在通信时是否已经送达。接下来, 服务器 TCP 模块会将 TCP 头部传递给 IP 模块, 并委托 IP 模块向客户端返回响应。然后, 网络包就会返回到客户端, 通过 IP 模块到达 TCP 模块, 并通过TCP 头部的信息确认连接服务器的操作是否成功。 如果 SYN 为 1 则表示连接成功, 这时会向套接字中写入服务器的?IP 地址、 端口号等信息, 同时还会将状态改为连接完毕。 此外, 客户端需要将 ACK 比特设置为 1 并发回服务 收发数据 将 HTTP 请求消息交给协议栈 :数据收发操作是从应用程序调用 write 将要发送的数据交给协议栈开始的协议栈收到数据后执行发送操作,如下步骤:??首先, 应用程序在调用 write 时会指定发送数据的长度, 在协议栈看来, 要发送的数据就是一定长度的二进制字节序列而已。其次, 协议栈并不是一收到数据就马上发送出去, 而是会将数据存放在内部的发送缓冲区中, 并等待应用程序的下一段数据。 对较大的数据进行拆分 :?HTTP 请求消息一般不会很长, 一个网络包就能装得下, 但如果其中要 ?MTU?: 一个网络包的最大长度, 以太网中一般为 1500 字节。 使用 ACK 号确认网络包已收到 :? 首先, 客户端在连接时需要计算出与从客户端到服务器方向通信相关的序号初始值,并将这个值发送给服务器。接下来, 服务器会通过这个初始值计算出 ACK 号并返回给客户端?。 初始值有可能在通信过程中丢失, 因此当服务器收到初始值后需要返回 ACK 号作为确认。 同时, 服务器也需要计算出与从服务器到客户端方向通信相关的序号初始值, 并将这个值发送给客户端。 接下来像刚才一样, 客户端也需要根据服务器发来的初始值计算出 ACK 号并返回给服务器 。 到此。序号和 ACK 号都已经准备完成了,接下来就可以进入数据收发阶段了。 数据收发操作本身是可以双向同时进行的, 但 Web 中是先由客户端向服务器发送请求, 序号也会跟随数据一起发送。 然后, 服务器收到数据后再返回 ACK 号。 从服务器向客户端发送数据的过程则正好相反。小结:通过“序号”和“ACK 号”可以确认接收方是否收到了网络包。? ? ? 调整 ACK 号等待时间 :?根据网络包平均往返时间调整 ACK 号等待时间,首先是返回 ACK 号的等待时间(这个等待时间叫超时时间)当网络传输繁忙时就会发生拥塞, ACK 号的返回会变慢, 这时我们就必须将等待时间设置得稍微长一点, 否则可能会发生已经重传了包之后, 前面的 ACK 号才姗姗来迟的情况。 因此, TCP 采用了动态调整等待时间的方法, 这个等待时间是根据 ACK 号返回所需的时间来判断的。 具体来说, TCP 会在发送数据的过程中持续测量 ACK 号的返回时间,?如果 ACK 号返回变慢, 则相应延长等待时间; 相对地, 如果 ACK 号马上就能返回, 则相应缩短等待时间 。 接收 HTTP 响应消息 :首先, 浏览器在委托协议栈发送请求消息之后, 会调用 read 程序?来获取响应消息。 然后, 控制流程会通过 read 转移到协议栈 , 然后协议栈会执行接下来的操作。 和发送数据一样, 接收数据也需要将数据暂存到接收缓冲区中,操作过程如下:首先, 协议栈尝试从接收缓冲区中取出数据并传递给应用程序, 但这个时候请求消息刚刚发送出去, 响应消息可能还没返回。 响应消息的返回还需要等待一段时间, 因此这时接收缓冲区中并没有数据, 那么接收数据的操作也就无法继续。 这时, 协议栈会将应用程序的委托, 也就是从接收缓冲区中取出数据并传递给应用程序的工作暂时挂起 , 等服务器返回的响应消息到达之后再继续执行接收操作。简而言之,首先, 协议栈会检查收到的数据块和TCP 头部的内容, 判断是否有数据丢失, 如果没有问题则返回 ACK号。 然后,协议栈将数据块暂存到接收缓冲区中, 并将数据块按顺序连接起来还原出原始的数据, 最后将数据交给应用程序。 ?客户端与服务端断开连接:?以 Web 为例, 浏览器向 Web 服务器发送请求消息, Web 服务器再返回响应消息, 这时收发数据的过程就全部结束了, 服务器一方会发起断开过程。 当然, 可能也有一些程序是客户端发送完数据就结束了, 不用等服务器响应, 这时客户端会先发起断开过程。 这一判断是应用程序作出的, 协议栈在设计上允许任何一方先发起断开过程。以服务器一方发起断开过程为例,首先, 服务器一方的应用程序会调用 Socket 库的 close 程序。 然后, 服务器的协议栈会生成包含断开信息的 TCP 头部, 具体来说就是将控制位中的 FIN 比特设为 1。 接下来,协议栈会委托 IP 模块向客户端发送数据。同时,服务器的套接字中也会记录下断开操作的相关信息。接下来轮到客户端了。 当收到服务器发来的?FIN 为 1 的 TCP 头部时,客户端的协议栈会将自己的套接字标记为进入断开操作状态。然后, 为了告知服务器已收到 FIN 为 1 的包, 客户端会向服务器返回一个 ACK号。 这些操作完成后, 协议栈就可以等待应用程序来取数据了。 ? ? ? ? 过了一会儿, 应用程序就会调用 read 来读取数据 。 这时, 协议栈不会向应用程序传递数据 , 而是会告知应用程序(浏览器) 来自服务器的数据已经全部收到了。 根据规则, 服务器返回请求之后, Web 通信操作就全部结束了,收到服务器返回的所有数据客户端应用程序会调用 close 来结束数据收发操作, 这时客户端的协议栈也会和服务器一样, 生成一个 FIN 比特为1 的 TCP 包, 然后委托 IP 模块发送给服务器。 一段时间之后, 服务器就会返回 ACK 号,到此, 客户端和服务器的通信就全部结束了。 删除套接字:?和服务器的通信结束之后, 用来通信的套接字也就不会再使用了, 这时我们就可以删除这个套接字了。 不过, 套接字并不会立即被删除, 而是会等待一段时间之后再被删除。 包的基本知识 :?TCP 模块在执行连接、 收发、 断开等各阶段操作时, 都需要委托 IP 模块将数据封装成包发送给通信对象。 下面介绍一下 IP 模块是如何将包发送给对方的?网络包的一些基本知识。 首先, 包是由头部和数据两部分构成的。 头部包含目的地址等控制信息, 大家可以把它理解为快递包裹的面单; 头部后面就是委托方要发送给对方的数据, 也就相当于快递包裹里的货物。 ? ? ? ? ?首先, 发送方的网络设备会负责创建包, 创建包的过程就是生成含有正确控制信息的头部, 然后再附加上要发送的数据。 接下来, 包会被发往最近的网络转发设备。 当到达最近的转发设备之后, 转发设备会根据头部中的信息判断接下来应该发往哪里。 这个过程需要用到一张表, 这张 ? 路由器和集线器的作用 ?TCP/IP 包包含如下两个头部:(a) MAC 头部(用于以太网协议);(b) IP 头部(用于 IP 协议) 包收发操作 :?包收发操作的起点是 TCP 模块委托 IP 模块发送包的操作,这个委托的过程就是 TCP 模块在数据块的前面加上TCP 头部, 然后整个传递给 IP 模块, 这部分就是网络包的内容。 与此 ? ? ? ? ?包送达对方之后, 对方会作出响应。 返回的包也会通过转发设备发送回来, 然后我们需要接收这个包。 接收的过程和发送的过程是相反的, 信息先以电信号的形式从网线传输进来, 然后由网卡将其转换为数字信息并传递给 IP 模块。 接下来, IP 模块会将 MAC头部和 IP 头部后面的内容, 也就是 TCP 头部加上数据块, 传递给 TCP模块。 生成以太网用的 MAC 头部 :?生成了 IP 头部之后, 接下来 IP 模块还需要在 IP 头部的前面加上 MAC头部,MAC 头部是以太网使用的头部, 它包含了接收方和发送方的 MAC 地址等信息。MAC 头部的开头是接收方和发送方的 MAC 地址, 大家可以认为它们和 IP 头部中的接收方和发送方 IP 地址的功能差不多, 只不过 IP 地址的长度为 32 比特, 而 MAC 地址为 48 比特。 ARP 查询目标路由器的 MAC 地址 :?使用 ARP(Address Resolution Protocol, 地址解析协议) 就是利用广播对所有设备提问: “×× 这个 IP 地址是谁的? 请把你的 MAC 地址告诉我。 ”然后就会有人回答: “这个 IP 地址是我的, 我的 MAC 地址是 ××××。 ”如果对方和自己处于同一个子网中, 那么通过上面的操作就可以得到对方的 MAC 地址 。 然后, 我们将这个 MAC 地址写入 MAC 头部,MAC 头部就完成了。 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 4:11:39- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |