文章目录

TCP/IP五层协议栈应用层xml (可读性比较好 但是运行效率不高)json(可读性好 但是运行效率不高)prtobuffer(可读性不好 但是运行效率很高)

传输层UDP

TCPTCP数据解读32位序号32位确认序号4位首部的长度保留位6位标志位字段16位窗口大小16位校验和16位紧急指针选项

确认应答(保证可靠传输的核心机制)超时重传(相当于对确认应答做了补充)连接管理(TCP保证可靠性的机制)建立连接 三次握手如何断开连接(四次挥手)

滑动窗口流量控制拥塞控制延时应答捎带应答面向字节流异常处理

网络层IP协议

数据链路层物理层

作者主页:Java冰激凌 专栏链接:JavaEE

TCP/IP五层协议栈

应用层

在应用层中 最重要的就是数据要在网络中进行传输 所以说 在应用层中最主要的是要约定一个“应用层协议”在约定协议的时候 主要包含两个工作

明确传输的信息明确数据的组织格式

当然因为应用层使用的广泛 业界也有不少的优秀的协议模板 我们大概来看一下

xml (可读性比较好 但是运行效率不高)

他采用的数据组织格式使用了标签 有点类似于HTML的语法 我们来简单的看一下 数据组织格式大概如下 其中 标签名表示的就是Key 数据表示的就是Value 也是Key-Value结构的

json(可读性好 但是运行效率不高)

json是当下最流行使用的数据组织格式 他也是采用Key-Value的结构的 但是相比较于xml来说还是更加高效的 他的结构是这样的:

通过{}构成了键值对结构一个{}中有很多个键值对键值对之间使用逗号分割键和值之间使用冒号分割要求键必须是字符串类型的值运行很多类似(数字 字符串 布尔 数字 甚至是另一个json) json中表示字符串 单引号和双引号都可以 最后一个键值对后面可以有逗号 也可以没有 json要求key一定是字符串 因此 key这里的引号可以省略 除非key中包含了一些特殊符号 (比如想空格 或者-…) 必须要加上引号

prtobuffer(可读性不好 但是运行效率很高)

prtobuffer是一种二进制格式的数据 同时再通过一个IDL文件来描述这个数据格式 IDL只是起到了一个辅助开发的效果 并不会真正传输 传输的只是二进制的数据 虽然我们编写的是文本 但是传输的时候会被压缩为二进制的 甚至会重新进行编排

设计应用层协议 是一件普通的事情 设计应用层协议 要做的工作

明确传输的信息(根据需求)明确传输的格式(参考现有的模板 xml json protobuffer) 当然 http 也是业界优秀的协议

传输层

我们之前已经提到过 端口号是有0-65535 但是其中也有一些知名的端口号 就例如0-1024被专门划分出来固定分配个对应的应用 其中 传输层最常见的协议 :TCP 和 UDP 我们来详细了解一下

UDP

我们上一篇文章已经介绍了UDP的基本特点:无连接 不可靠传输 面向数据报 全双工 忘记的或者不知道的可以点击下面蓝色字体跳转 网络编程套接字 其中 源端口号就是代表发送数据的端口 目的端口代表数据要发送给哪个端口 长度代表这个数据报的长度 校验和我们来着重的介绍一下 校验和类似于我们的长度校验 首部校验 我们的校验和中存储的可能是一个数字 这个数字可能是代表传输的数据的个数 也可以是根据数据内容计算出来的校验和 如果数据出错 那么根据校验和 我们就可以明确的知道 这个包当前的数据时错误的 我们都知道孔子的论语的命名 都是取的文首句的二三字 就是类似的原理

其中还有提到的是 因为UDP是发送的数据报 所以说UDP的数据每次发送的是有上限的 那么对于一个很大的数据如果使用UDP传输该如何传输呢?此时可以在应用层 针对较大的数据报来进行分包 然后通过多个UDP来进行传输 这个时候接收方再通过收到的多个包来进行拼接成完整的数据 但是这个并不是一个好的方法 因为我们要考虑到的东西会很多 例如我们数据拆包之后 发送到接收方的时候接收方如何进行组包 还要考虑 如果发生了丢包该怎么办 (因为UDP是不可靠传输)那么此时 最好的解决策略就是使用TCP 对于TCP是面向字节流的 是没有长度大小的限制的

TCP

TCP是一块难啃的骨头 但是全程无尿点 TCP的各种机制精妙绝伦

TCP数据解读

我们先来简单的介绍一下TCP的数据报格式 首先和我们的UDP一样 都拥有这源端口号、目的端口号

32位序号

每个TCP报文段都包含一个序号字段用于标识该报文段所携带的数据块在整个数据流中的位置 发送 方在发送数据时 会给每个数据块分配一个唯一的序号 接收方在接收数据时 会根据序号来识别数据块的顺序以及是否有数据丢失或重复

32位确认序号

接收方在接收到数据后 需要向发送方发送一个确认报文段其中包含一个确认序号字段 用于回应发送方已经成功接收到的数据的最高序号(即已经被正确接收的数据的下一个字节序号 )发送方在收到确认报文段后 就可以知道接收方已经成功接收到了哪些数据 可以继续发送下一批数据块

4位首部的长度

4个bit位 可以表示0-15 表示TCP报头的长度 此处的单位是4字节 例如1111 代表 15 * 4 = 60字节

保留位

暂时未启动 为了以后升级预留的空间

6位标志位字段

这个字段中的每一个代表着不同的功能 这6个标志位分别是:URG、ACK、PSH、RST、SYN和FIN

URG(紧急位):用于指示当前报文段中是否包含紧急数据。如果这个标志被设置为1,那么表明当前报文段中包含了紧急数据,需要发送方和接收方进行特殊处理ACK(确认位):用于确认收到的数据。如果这个标志被设置为1,那么表明当前报文段是一个确认报文段,用于确认前面发送的数据已经被正确地接收到了PSH(推送位):用于通知接收方应该立即将报文段中的数据推送给应用程序而不是等待缓存填满。如果这个标志被设置为1,那么表明发送方要求接收方应该受理当前数据段而不需要等待缓存区填满SYN(同步位):用于建立连接。如果这个标志被设置为1,那么表明当前报文段用于建立连接,请求对方回复一个ACK报文段以确认连接FIN(结束位):用于结束连接。如果这个标志被设置为1,那么表明当前报文段用于结束连接,请求对方回复一个ACK报文段以确认连接断开

16位窗口大小

接收方可以接收而不会拥塞的字节数的最大值

16位校验和

类似于UDP的检验和

16位紧急指针

用于指示报文段中的紧急数据的位置,也就是报文段中紧急数据的起始偏移量。当URG标志被设置为1时,紧急指针就变得有意义了 如果没有紧急数据的话 这个紧急指针也可以不存在 一般用于一个需要快速响应的操作 例如cmd窗口中输入了ctrl+c 强制停止 就需要立即处理停止操作

选项

这个选项是可以有一个 也可以有多个 当然也可以是没有的

确认应答(保证可靠传输的核心机制)

关键就是在给接收方发送消息后 接收方会返回一个应答报文ACK表示接收方已经收到了 确认序号就类似于我们平时的聊天 可能一次发送一个消息 对方回复收到 代表对方已经收到了 如果其中发生了丢包事件 那么不管是哪边丢失 都能保证消息的送达 例如假设我们的发送方要发送的消息丢包了 隔了一段时间没有收到接收方发回的ACK 那么我们就认为是丢包了 就会给接收方重发消息 那么接收方发送的ACK丢了怎么办呢? 还是一样的道理 当发送方发送数据后 没有收到接收方发回的ACK 就认为是丢包了 会出发超时重传(稍等就会介绍到)重新发送消息给接收方 接收方收到一看 这不是刚刚发过的数据吗 那么接收方就明确知道自己发送的ACK丢了 就会重新发送ACK给发送方 我们来简单画一个序号和确认序号对应到TCP模型中

超时重传(相当于对确认应答做了补充)

如果出现了丢包 那么我们的超时重传机制就要启动了 还是我们刚刚的举例 假设我们还是主机A和主机B 好 我们再来看一些确认应答ACK丢失 重传的这个时间频率也不是固定的 一般来说会逐渐变大 重传的频率会逐渐降低 如果发送两次 丢包概率会大大降低 假设发送失败的概率是10% 失败两次的概率假设1% 三次的概率假设0.1% 多次重传 概率会大大降低 (在保持网络正常的情况下)但是如果出现了连续10次 或者100次 就认为这个连接已经断开了 相信大家都不免遇到网络不好一直在断线重连吧

但是如果是ACK丢了 触发了超时重传 这个时候会导致出现接收方收到了重复的消息 其他的消息问题不大 但是涉及到钱就不一样了 所以 在TCP的内部会有一个去重的操作 接收方收到的数据会先放到操作系统内核的"接收缓存区"中 (是一个内存空间 也可以认为是一个阻塞队列)每当收到了新的数据 TCP就会根据序号 来检查这个数据是不是在接收缓冲区中已经存在了 如果不存在就放进去 如果存在 就直接丢弃这样的操作保证了应用程序中调用socket api拿到的这个数据一定是不重复的 重传如果失败 可能还会尝试 也不会无休止的重传 如果连续几次都不行 那么就认为这个网络可能是遇到了严重的情况 (自动的断开TCP的连接)

连接管理(TCP保证可靠性的机制)

TCP的状态 (两种常见的状态) LISTEN 表示服务器启动成功 端口绑定成功 随时可以有客户端来建立连接 ESTABLISHED 表示客户端已经连接成功 随时可以进行通信了 以下是一个经典面试题 TCP的三次握手四次挥手

建立连接 三次握手

客户端和服务器经过三次交互完成了建立的过程 客户端是主动发起请求的一方 所以会从客户端先开始向服务器端发送一个SYN同步报文段 服务器收到的话 会返回一个ACK报文段 并且也会发送一次SYN报文段 而且这两个报文段大概率是会合二为一的 因为封装两个报文段肯定没有一次来的高效 之后客户端收到之后会返回一个ACK作为应答 三次握手有啥用?和可靠性有啥关系? 三次握手相当于是在投石问路 主要就是为了确认客户端服务器双方的接收和发送功能是否正常 举个栗子 : 就像我们打电话的时候 首先 我: 喂 能听到吗? (此时当对方听到我说话对方就明确了我的发送能力是没问题的) 对方:可以听到! 你能听到我说话吗?(此时当我收到这个消息之后我就明确 我的发送能力和对方的接收能力与发送能力都是没问题的 但是当前对方还不知道对方的发送功能是否正常 于是我再告诉他) 我:可以的可以的(此时双方都明确了双方的接收和发送能力都是完整的)

经历了三次握手 通信双方都验证了各自的发送能力和接收能力都可以 接下来就可以继续进行可靠传输了当然 三次握手不单单交互的是这些 还会协商一些具体参数 就像我们打电话的时候 问问对方吃饭了没 在哪里了这些

如何断开连接(四次挥手)

四次挥手 双方各自向对方发送了FIN(结束报文段) 请求 并且各自给对方一个ACK确认报文 三次挥手 一定是客户端主动发起的主动发起的一方才叫客户端 四次挥手 可能是客户端发起的 也可能是服务器主动发起的 三次挥手 中间两次是可以合并的 四次挥手 中间两次有时候合并不了 有时候可以合并 假设 我们客户端要跟服务器断开连接 首先我们的客户端会给服务器发送一个YIN报文段表示要断开连接 服务器收到之后会立即返回一个ACK报文段 之后服务器还会返回一个YIN报文段 (为何这两次不会合并 这两次是大概率不会合并的 因为ACK的返回是内核态处理的 而YIN是代码负责的) 之后客户端会返回一个ACK 此时连接断开 不能合并的原因? 在于B发送ACK和B发送FIN的时机是不同的 在四次挥手中 B给A发的ACK是内核负责的 B给A发送的FIN是用户代码负责的 只有在代码中调用了socket.close()才会发送(FIN)如果这两个操作之间的时间差比较大 就不能合并了 如果时间差比较小 可能会合并的(延时应答和捎带应答) 其中需要注意到的是 当客户端发送FIN报文段之后 会等待服务器的ACK 收到ACK之后 客户端不会立马断开连接 会等待服务器的FIN请求 之后再给服务器返回一个ACK报文段 那么发送报文段之后就会断开吗 nonono 还是不会立即断开 因为如果客户端发送的ACK丢失之后 那么服务器没有收到ACK 就会触发超时重传机制 如果此时释放之后就会收不到请求 所以 其实断开之后 客户端和服务器的连接还会存在一定的时候 我们举个栗子 A为客户端 B为服务器 假设A和B是一对恋人 今天他们吵架了 要分手了 A:分手吧(FIN)(此时发送FIN请求 如果没有收到B的回应 就会认为是他没有听到 会重新说 分手) B:啊?(ACK)(此时发送ACK请求 表示已经收到了消息) B:(经过考虑)好!分手吧(FIN)(此时经过思考 也就是过了一段时间后 就会发送FIN) A:行 分手就分手!(ACK)(此时A已经名义上和B分手了) (但是A和B的连接不会马上断开 因为要分开 但是彼此的东西太多了 要经过一段时间的才能彻底断开 然后经过一段时间才会忘掉 断开连接后还要存在一定的时间)

TCP/IP 模型中哪一层处理传输的可靠性、流量控制和错误控制(传输层)

此外 我们还要认识两个状态 CLOSE_WAIT 四次挥手挥了两次之后出现的状态 这个状态就是在等待代码中调用socket.close() 方法 来进行后续的过程 (ps:正常情况下 一个服务器上不应该存在大量的CLOSE_WAIT 如果存在 说明大概率是代码bug 导致close没有被执行到) TIME_WAIT 谁主动发起FIN 谁就进入TIME_WAIT 起的效果就是给最后一次ACK提供重传的机会(因为在A发送完ACK之后 可能会出现ACK丢包的情况 如果出现最后一个ACK丢包了 那么B在一段时间没有接收到ACK 可能会认为是FIN丢包了 会进行重传(超时重传) 那么如果现在A已被释放了 那么B这个资源就无法被释放 导致的可能会在服务器淤积过多的数据)因此 要进入TIME_WAIT状态 不要释放的太早 要等待一段时间 确保B不会再重传FIN 之后 再去销毁 即使TCP做了很多工作来保证可靠 但是TCP也在很怒力的提高传输速度

滑动窗口

滑动窗口所存在的意义 就是在保证可靠性的前提下 尽可能的提高传输的速度 如果一次发送的数量为一 那么我们每一次发送后都需要等待服务器的ACK 如此一来会浪费大量的等待时间 这明显不是我们想看到的 所以在这个基础上 滑动窗口就是为了解决这个问题来的

滑动窗口的工作原理是什么呢? 如果一次批量发送的数据为N 统一等待一波 此时这里N成为窗口大小 “滑动”的意思是 并不用把N组数据的ACK都等到了 才继续往下发送 而是收到一个ACK 就继续往下发一组

我们来看一个图 我们这样做的好处是 不需要一直等待1001、2001、3001、4001响应 当前我们同时等待的是四组ACK 只要1001到了 就可以往下多发一组(4001 - 5000)此时我们等待ACK的范围就改变了 (2001 - 5001) 一份等待的时间 等待了多组ACK 就把等待多份ACK的时间压缩成一份了

那么我们就诞生出了新的问题 我们不等这个ACK直接发送不行吗?

等 必须等 TCP是可靠传输 可靠传输的一个组成必要就是确认应答

如果传输中提前到达了2001 1001还未收到呢?

出现这个情况是很正常的 首先我们要明确 在网络中传输有快有慢 有的选择了最优路径 有的选择了最差路径 所以会导致ACK的到达有快有慢 但是 当我们收到2001ACK/的时候 我们此时认为 从2001之前的数据已经全都被服务器接收到了 为何是这样呢 因为服务器的确认序号是根据序号来进行返回的 而且这个序号只增不减 当我们收到2001 的ACK的时候 就证明服务器已经收到了2001前的所有数据 所以此时我们并不需要关注1001的ACK是否丢包或者未到达 直接滑动窗口即可 并且 这个窗口大小越大 我们可以认为传输速度越快

我们加入滑档窗口之后会有一个核心问题 丢包 !

因为我们发送的是多组的数据 当我们进行大批量发送的时候 当网络不稳定的时候 这个时候出现丢包的概率就变得很大 ACK丢了

这个是我们构造出的丢包的情况 我们其中 1001、3001、4001的ACK都发生了丢失 但是我们是正常收到了2001、5001、6001 其实当我们收到2001的ACK的时候 就可以证明1001的ACK已经被服务器发送 也就代表着服务器已经收到1-1000的数据 所以 1001的ACK是否收到 已经变的不重要了ACK确认序号的特地含义就保证了后一条ACK能够涵盖前一条

这个我们也来举个栗子~ 这个就好比找对象 首先我们认为谈恋爱有以下步骤

拉小手抱抱么么哒……(以下内容付费观看) 这几个步骤中 后者肯定是涵盖前者的 当你们可以么么哒的时候 肯定拉小手 抱抱是肯定允许的

ACK也像是在升级 当你已经10级的时候 你肯定已经经历过5级、6级

数据丢了 如上图所示 当我们的1001-2000数据丢失的时候 服务器端会多次返回1001的ACK 代表1001之后的数据有丢包 没有收到 此时客户端会重复发送1001-2000 当服务器收到之后会继续返回7001的ACK

流量控制

流量控制是滑动窗口的延伸 目的是为了保证可靠性的同时尽可能提升传输效率

我们知道 在滑动窗口中 窗口越大 传输速度越快 但是我们在滑动窗口中 只考虑到了客户端 没有考虑到服务器 当发送方发的贼快的时候 但是接收方处理不过来 此时接收方就会直接把新收到的包给丢弃 之后发送方仍旧需要进行重传

流量控制的关键 就是能够衡量接收方的处理速度 此时直接使用接收方接收缓存区中剩余的大小来作为传输的效率

这个也有一点类似我们之前的生产者消费者模型 发送方就是生产者 接收方就是消费者 而接收方的接收缓存区就是交易场所

如果剩余空间比较大 就认为B的处理能力是比较强的 就可以发快点 反之慢点 通过ACK来返回剩余空间 通过TCP中的16位窗口大小来衡量当前接收方剩余的大小 其中有趣的是 当返回的窗口大小为0的时候 A会停止发送数据 但又不是完全不发 会定期的给客户端发送一个探测报文 这个探测报文不会发送任何数据 只是为了出发ACK 触发了ACK就可以知道当前的窗口大小是多少

拥塞控制

也是滑动窗口的延伸 也是限制滑动窗口发送的速率

拥塞控制衡量的是 发送方到接收方 这些链路之间 拥堵情况(处理能力)

A能够发多块 不光取决于B的处理能力 也取决于中间链路的处理能力

通过实验的方式 逐渐调整发送速度 找到一个比较合适的范围

发送方刚开始只会以一个比较小的数据包开始发送 如果数据包很流畅的到达了 就开始逐渐加大窗口大小 如果加大到一定的程度之后 出现 了丢包 那么发送方会急速缩小窗口大小 通过反复的增大和缩小 逐渐会找到一个合适的范围 拥塞窗口就会在这个界值中不断的变化 当他开始缩小的时候 会以指数级别的上升到刚刚的一半界值 然后再缓慢提升

我们还是来举一个例子

这个就好比找对象的感情

刚开始谈恋爱的时候 爱情是非常的甜蜜的 关系飞速上升 但是过一段时间之后 这个新鲜感已经过去了 然后吵架了 感觉就会掉落谷低 之后男生再哄一哄女生 又和好了 关系迅速升温到之间的一半 肯定不会有刚开始的甜蜜期亲密了 如此反复 经过很久之后就会趋于一个稳定的范围

延时应答

相当于流量控制的延伸 流量控制好比踩了一下刹车 使发送方不要发送的太快 延时应答就是在这个基础上 想要尽量的再多发送一些数据 就当发送端向接收端获取剩余空间的时候 接收端暂时不回答 而且尽量多处理一些数据 就可以让发送端多发送一些数据

捎带应答

其实三次握手就有使用到这个捎带应答 捎带应答就是准备好数据后 稍微等一等 如果有其他的数据要发送给接收端 就带上一起发送 这个很好理解

客户端和服务器之间的通信

一问一答 客户端发送一个请求 服务器返回一个对应的请求(浏览器)多问一答 上传文件一问多答 下载文件多问多答 直播、串流

面向字节流

因为TCP是面向字节流的 所以不可避免的会存在粘包问题 (不仅仅是TCP存在粘包问题 其他面向字节流的机制也存在 比如读文件) 那么什么是粘包问题呢? 假设我们当前A向B发送了3个TCP数据报 这些数据到达B之后 会进行分用 意味着把TCP进行解析了 取出了其中的应用层数据 放到接收缓冲区中 B的应用程序需要通过read的方式来读取接收缓存区中的数据 因为TCP是面向字节的 那么我们如何得知 从哪里到哪里就是一个完整的数据报呢? 如果没有一个额外的限制 其实就很难进行区分了 原因 TCP的报头是没有长度的 当前接收缓存区 可以视为分用后的数据 此时缓存区中是不带TCP的数据报头的 解决方案 关键就是也要在应用层协议这里加入包的边界 可以约定好在每个包以分号结尾在接收缓存区中以分号来进行切分即可

异常处理

进程终止 在进程毫无防备的情况下突然结束这个进程

TCP连接是通过socket来建立的 socket本质上是进程打开的一个文件 文件其实就存在于进程的PCB 里面有一共文件描述符表 每次打开一个文件 (包括sicket)都在文件描述符表中增加一项每次关闭一个文件 都在文件描述符表中删除一项如果直接杀死进程 PCB也就没了 文件描述符表也就没了 此时的文件相当于是自动关闭 这个过程其实和socket.close()一样 都会触发四次挥手

机器关机

这个很理解 按照正常的流程关机 会让操作系统去杀死所有的进程 然后进行关机 这个流程也会正常的出发四次挥手

机器掉电、网线断开

这个出现在台式机上比较常见 笔记本一般不会出现这个情况 因为笔记本都有内置电池 直接断开电源 操作系统不会有任何的反应时间 更不会有任何 的处理措施

B断电 如果B断电 意味着A发送的所有数据都不会再有ACK了 当A长时间收不到ACK 就会一直进行重传 重传几次后 A就会认为这个连接已经出现 严重的故障 就会主动放弃连接A断电

如果A断电 B就不知道当前是A挂了 还是A休息会儿再使用 因为B是服务器 B就会时不时的给A发送一个探测报文(心跳包)这个心跳包不带有任何数据 只是为了出发ACK 也就是看A服务器是否存活 如果收不到ACK 就认为出现了严重故障 B就会主动断开连接

TCP的特性介绍就撒花啦

总结一些面试题 TCP和UDP对比 啥时候使用TCP?

对可靠性有一定要求

啥时候使用UDP?

对可靠性要求不高 对效率要求更高

如何基于UDP实现可靠传输 本质上就算是再考TCP 只需要在应用层引入TCP的确认应答和超时重传机制即可

传输层的协议 只有TCP和UDP吗? 不是 在达能下常见的对抗性很高的游戏 使用的既不是TCP 也不是UDP

网络层

IP协议

4位版本:IP协议的版本号 当前只有两个取值 4 和 6 分别代表IPV4 和IPV64位首部长度:IP的报头和TCP类似 都是可变的 带有选项的(0-15)15 的实际标识的长度就是60TOS说是8位 可实际有效的只有4位 分别是 最小延时 最大吞吐量 最高可靠性 最小成本16位总长度 65535 类似于UDP的64k 如果超过64k IP协议自身实现了分包和组包这样的操作 这三个字段就是用来分包和组包的 如果整个数据报太长了 IP协议就会把这些数据报分割为多个小包 保证每个不会超过64k 然后就会按照顺序给小包标记片偏移 并且不是最后一个包的话 标记为为0 如果为最后一个包的话 会更改标记位为1 当标记位为1 的时候 就代表结束标记 这样接收方就可以根据标记判断是否发送完毕 然后根据片 偏移就可以将小包再次组合为一个数据报

如何基于UDP实现组包分包 就可以照抄IP

8位生存时间 :代表一个IP数据报可以在网络中还能存在多久 但是这个不是按照一个具体的时间来计算的 而且根据转发次数 每经过一次转发其中的时间就会减少1 当其中的值变为0之后 这个包就会丢失 这么做是为了避免出现有些数据报中的IP 可能永远是无法到达的 这样就会被在网络中进行无休止的转发 导致网络拥塞 设置了生存时间就不会出现这种问题了8位协议 :传输层使用的是哪种协议 TCP或者是UDP都有不同的取值16位首部校验和:也是用来验证数据是否正确

还是简单的回顾一下IP 源IP表示发件人地址 目的IP表示收件人地址 对于一个IPv4来说 一个IP地址本质上是32位的整数 通常会使用点分十进制来表示这个IP 三个点 把32位整数分成4个部分 每个部分1个字节 每个部分的取值就是0-255 IP地址是一个点分十进制构成的数据 IP地址分成了两个部分 网络号+主机号 网络号描述了当前的网段信息 主机号区分了局域网内部的主机

数据链路层

数据链路层主要的协议 叫做“以太网” 像平时的网线 就叫做“以太网线” 以太网数据帧很简单 就是帧头为一个目的地址和源地址 其中 这里的地址 可就不是咱们的IP地址啦 这个地址是一个物理地址称为“mac地址” mac地址做到了每个设备都是唯一的(每个网卡都是唯一的 这些网卡在出厂的时候已经被写死了) 其实ipv4和mac地址是同一时代的产物 当年网络层协议和数据链路层协议是各自独立研发出来的 mac地址和IP地址 有点重复了 IP用来表示一次传输过程中的起点和重点 mac用来表示传输过程中 任意两个相邻节点之间的地址 帧尾就是一个基于CRC算法的校验和 采用的循环冗余算法 把数据的每个字节依次相加 (当然数据很可能会溢出 不过这个没关系 溢出就溢出 没有影响)

物理层

由于物理层距离程序员比较遥远 俺也没有过多的了解 就不做介绍啦~

相关链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。