01TCP_IP协议
1. TCP/IP 模型
TCP/IP 协议模型(Transmission Control Protocol / Internet Protocol),包含了一系列构成互联网基础的网络协议,是 Internet 的核心协议。
基于 TCP/IP 的参考模型将协议分成四个层次,它们分别是链路层(网络接口层)、网络层、传输层和应用层。下图表示 TCP/IP 模型与 OSI 模型个层次的对关系。
TCP/IP 协议族按照层次由上到下,层层包装。最上面的是应用层,这里面有 http,ftp 等我们熟悉的协议。而第二层测试传输层,著名的 TCP 和 UDP 协议就在这个层次。第三层是网络层,IP 协议就在这里,它负责对数据加上 IP 地址和其他的数据以确定传输的目标。第四层是数据链路层,这个层次为待传送的数据加上一个以太协议头,并进行 CRC 编码,为最后的数据传输做准备。
上图清楚地表示了 TCP/IP 协议中每层的作用,而 TCP/IP 协议通信的过程其实就是对应着数据入栈和出栈的过程。入栈的过程,数据发送方每层不断地封装首部与尾部,添加一些传输的信息,确保能传输到目的地。出栈的过程,数据接收方每层不断地拆除首部与尾部,得到最终传输的数据。
2. 数据链路层
物理层负责 0、1 比特流与物流设备电压高低、光的闪灭之间的交互。数据链路层负责将 0、1 序列划分为数据帧从一个节点传输到邻近的另一个节点,这些节点是通过 MAC 来唯一标识的(MAC,物理地址,一个主机会有一个MAC)。
- 分装成帧:把网络层数据报加头加尾,封装成帧,帧头中包含源 MAC 地址和目的 MAC 地址。
- 透明传输:零比特填充、转义字符。
- 可靠传输:在出错率很低的链路上很少用,但是无线链路 WLAN 会用来保证可靠传输。
- 差错检测(CRC):接收者检测错误,如果发现差错,丢弃该帧。
3. 网络层
3.1 IP 协议
IP 协议是 TCP/IP 协议的核心,所有的 TCP、UDP、IMCP、IGMP 的数据都以 IP 数据都以 IP 数据格式传输。到注意的是,IP 不是可靠协议,也就是说,IP 协议没有提供一种数据未传达以后的处理机制,这被认为是上层协议 TCP 或者 UDP 要做的事情。
(1)IP 地址
在数据链路层中我们一般通过 MAC 地址来识别不同的节点,而在 IP 层我们也要有一个类似的地址标识,这就是 IP 地址。
32 位 IP 地址分为网络位和地址位,这样做可以减少路由器中路由表记录的数目,有了网络地址,就可以限定拥有相同网络地址的终端都在同一个范围内,那么路由表只需要维护一条这个网络地址的方向,就可以找到相应的这些终端。
- A 类 IP 地址:0.0.0.0 ~ 127.0.0.0
- B 类 IP 地址:128.0.0.0 ~ 191.255.0.0
- C 类 IP 地址:192.168.0.0 ~ 239.255.255.0
(2)IP 协议头
这里介绍一下 8 位的 TTL 字段。这个字段规定该数据包在穿越多少个路由之后才会被抛弃。某个 IP 数据包每穿过一个路由器,该数据包的 TTL 数值就会减少 1,当该数据包的 TTL 成为 0,它就会被自动抛弃。
这个字段的最大值也就是 255,也就是说一个协议包也就在路由里穿行 255 次就会被抛弃了,根据系统的不同,这个数字也不一样,一般是 32 或者是 64。
3.2 ARP 及 RARP 协议
ARP 是根据 IP 地址获取 MAC 地址的一种协议,相反的,RARP 是一种根据 MAC 地址获取 IP 的一种协议。
ARP(地址解析)协议是一种解析协议,本来主机是完全不知道这个 IP 对应的是哪个主机的那个接口,当主机要发送一个 IP 包的时候,会首先查一下自己的 ARP 高速缓存(就是一个 IP-MAC 地址对应表缓存)。
如果查询的 IP-MAC 值对不存在,那么主机就向网络发送一个 ARP 协议广播包,这个广播包里面就有待查询的 IP 地址。直接接收到这份广播的包的所有主机都会查询自己的 IP 地址,如果收到广播包的某一个主机发现自己符合条件,那么就准备好一个包含自己 MAC 地址的 ARP 包传送给发送 ARP 广播的主机。而广播主机拿到 ARP 包后会更新自己的 ARP 缓存(就是存放 IP-MAC 对应的地方)。
3.3 ICMP 协议
IP 协议并不是一个可靠的协议,它不保证数据被送达,那么,自然地,保证数据送达的工作应该有其他的模块来完成。其中一个重要的模块就是 ICMP(网络控制报文)协议。ICMP 不是高层协议,而是网络层(与 IP 协议同层)的协议。
(1)ping
ping 可以说是 ICMP 的最著名的应用,是 TCP/IP 协议的一部分, 利用 ping 命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。
ping 这个单词源自声呐定位,而这个程序的作用也确实如此,它利用 ICMP 协议包来侦测另一个主机是否可达。原理是用类型为 0 的 ICMP 发请求,受到请求的主机则用类型码为 8 的 ICMP 回应。
(2)traceroute
traceroute 是用来侦测主机到目的主机之间所经路由情况的重要工具,也是最便利的工具。
traceroute 的原理是非常有意思的,它收到目的主机的 IP 后,首先给目的主机发送一个 TTL=1 的 UDP 数据包,而经过的第一个路由器收到这个数据包以后,就自动把 TTL 减 1 ,而 TTL 变为 0 以后,路由器就把这个包给抛弃了,并且同事产生一个主机不可达的 ICMP 数据报给主机。主机收到这个数据报以后再发送一个 TTL=2 的 UDP 数据报给目的主机,然后刺激第二个路由器给主机发 ICMP 数据报。如此往复直到到达目的主机。这样,traceroute 就拿到了所有的路由器 IP。
4. TCP 工作流程
4.1 TCP 的三次握手
TCP 是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化。三次握手的目的是同步连接双方的序列号和确认号,并交换 TCP 窗口大小信息。
理解 TCP 的全双工工作模式是理解 三次握手和四次挥手的关键。
—— SYN(synchronous 建立连接) —— ACK(acknowledgement 确认)
—— Seq(Sequence number 顺序号码)
-
第一次握手:建立连接。
请求新的 TCP 连接时,客户端要向服务端发送一个连接请求报文段。这个报文段中设置了一个特殊 SYN 标记,说明这是一个连接请求。将 SYN位 置为 1, Seq 置为 x,然后客户端进入 SYN_SEND 状态,等待服务器的确认。
-
第二次握手:服务器收到 SYN 报文段。
服务器收到客户端的 SYN 报文段,需要对这个报文段进行确认,设置 ACK 为 x+1 (Seq+1);同时,服务器自己还要发送 SYN 请求信息,将 SYN 位置为1,Seq 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态,说明连接请求已被接受。
-
第三次握手:客户端收到服务器的 SYN+ACK 报文段。
客户端收到服务器的 SYN+ACK 报文段后,将 ACK 设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务端都进入 ESTABLISHED 状态,完成 TCP 三次握手。(现代的 TCP 栈都允许客户端在这个请求报文中发送数据。)
—— 与其叫三次握手,还不如叫三次伸手。
—— 之所以需要三次握手的一个原因就是 TCP 是全双工的,需要彼此确认可以收到信息。
—— 之所以需要三次握手的另一个原因就是 Seq+1 可以确保实时性,避免响应了别的连接。
—— 三次握手和后面的四次挥手,一般都是只发送 TCP 包头。
4.2. 为什么要三次握手
- 为了防止已失效的连接请求报文段突然又传送到了服务器,因而产生错误。
- 具体例子:“已失效的连接请求报文段”的产生可能在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段,但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的连接已经建立,并一直等待 client 发来数据。这样, server 的很对资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况, client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。
4.3. TCP 的四次挥手
—— FIN( 结束标志,关闭连接) —— ACK(acknowledgement 确认)
—— Seq(Sequence number 顺序号码)
- 第一次挥手:主机1(可以是客户端也可以是服务端),设置 Seq,向主机2 发送一个 FIN 保温段;此时主机1 进入 FIN_WAIT_1 状态;这表示主机1 没有信息要发送给主机2 了。
- 第二次挥手:主机2 收到了 主机1 发送的 FIN 报文段,向主机1 回一个 ACK 报文段, ACK 为 Seq 加 1;主机1 进入 FIN_WAIT_2 状态;主机2 告诉主机1,我“同意”你的关闭请求。
- 第三次挥手:主机2 向主机1 发送 FIN 报文段,请求关闭连接,同时主机2 进入 LAST_ACK 状态。
- 第四次挥手:主机1 收到主机2 发送的 FIN 报文段,向主机2 发送 ACK 报文段,然后主机1 进入 TIME_WAIT 状态;主机2 收到主机1 的 ACK 报文段以后,断开连接;此时,主机1 等待 2MSL (最大报文生存时间)后依然没有收到回复,则证明 Server 端(主机2) 已正常关闭,那好,主机1 也可以关闭连接了。
—— 主机1需要先说“我没有数据了”;然后主机2说“我知道你没有数据了”;再然后主机2说“我也没有数据了,可以断开连接了”;最后主机1说“我也知道你没有数据了,那我断开连接了”。
4.4. 为什么要四次挥手
TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着,当主机1 发出 FIN 报文段时,只是表示主机1 已经没有数据要发送了,主机1 告诉主机2 ,它的数据已经全部发送完毕了;但是,这个时候主机1 还是可以接收来自主机2 的数据;当主机2 返回 ACK 报文段时,表示它已经知道主机1 没有数据发送了,但是主机2 还可以发送数据到主机1的;当主机2 也发送了 FIN 报文段时,这个时候就表示主机2 也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。
4.5 第四次挥手为什么要等 2MLS
—— MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
-
保证 TCP 协议的全双工连接能够可靠关闭:如果主机1 直接 CLOSED 了,那么由于IP 协议不可靠性或是其他网络原因,导致主机2 没有收到主机1 最后回复的 ACK。那么主机2 就会在超时之后继续发送 FIN,此时由于主机1 已经 CLOSED了,就找不到与重发的 FIN 对应的连接了。所以,主机1 不是直接进入 CLOSED,而是要保持 TIME_WAIT,当再次收到 FIN 的时候,能够保证对方收到 ACK,最后正确的关闭连接。
-
保证这次连接的重复数据段从网络中消失:如果主机1 直接 CLOSED,然后又再向主机2 发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达主机2,由于新老连接的端口号是一样的,TCP 协议就认为那个延迟的数据属于新连接,这样就和真正的新连接的数据包发生混淆了。所以 TCP 连接还要在 TIME_WAIT 状态下等待 2 倍 MSL,这样可以保证本次连接的所有数据都从网络中消失。
4.5. 一个完整的 TCP 连接
5. UDP 工作流程
6. TCP/UDP 比较
- TCP 面向连接,发送数据前需要建立连接,UDP 是无连接的,即发送数据之前不需要建立连接。
- TCP 提供可靠的服务。也就是说,通过 TCP 连接传输的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。(TCP 通过校验和、重传控制、序号标识、滑动窗口确认应答实现可靠传输。)
- UDP 具有较好的实时性,工作效率比 TCP 高,适用于高速传输和实时性有较高要求的通信或 广播通信。
- 每一条 TCP 连接只能是点到点的;UDP 支持一对一、一对多、多对一、多对多的交互通信。
- TCP 对系统资源要求较多,UDP 对系统资源要求较少。
7. DNS
DNS(Domain Name System,域名系统),是因特网上作为域名和 IP 地址相互映射的一个分布式数据库,能够是用户更方便地访问互联网,而不用去记住能够被机器直接读取的 IP 数串。通过主机名,最终得到该主机对应的 IP 地址的过程叫做域名解析(或主机名解析)。DNS 是典型的应用层协议。
注意和 ARP 及 RARP 协议区分,DNS 是把字符串网址(如 www.baidu.com)转换为 IP 地址。而ARP 及 RARP 协议是进行主机 MAC 地址与 IP 地址之间的转换。
https://zhuanlan.zhihu.com/p/339237818
https://www.pianshen.com/article/5087169905/
https://blog.csdn.net/hehmxy/article/details/102015137
8.创建流程
1.2. UDP 创建流程
(1)主机 A:
- 创建 socket ,使用 socket 函数
- 准备通信地址,使用结构体类型
- 绑定 socket 和通信地址,是用 bind 函数
- 进行通信,使用 read / write 函数(应该是 recvfrom / sendto)
- 关闭 socket,使用 close 函数
(2)主机 B:
- 创建 socket,使用 socket 函数
- 准备通信地址,使用主机 A 的地址
- 绑定 socket 和通信地址,使用 bind 函数
- 进行通信,使用 read / write 函数(应该是 recvfrom / sendto)
- 关闭 socket,使用 close 函数
1.3. TCP 创建流程
(1)服务端:
- 创建 socket,使用 socket 函数
- 准备通信地址,使用结构体类型
- 绑定 socket 和通信地址,使用 bind 函数
- 监听,使用 listen 函数
- 响应客户端的连接请求,使用 accept 函数
- 进行通信,使用 send / recv 函数
- 关闭 socket,使用 close 函数
(2)客户端:
- 创建 socket,使用 socket 函数
- 准备通信地址,使用服务器的地址
- 连接 socket 和通信地址,使用 connect 函数
- 进行通信,使用 send / recv 函数
- 关闭 socket,使用 close 函数
9.单工,半双工和全双工有何区别和联系
- 单工数据传输只支持数据在一个方向上传输;在同一时间只有一方能接受或发送信息,不能实现双向通信,举例:电视,广告。
- 半双工数据传输允许数据在两个方向上传输;但是在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;在同一时间只可以有一方接受或发送信息,可以实现双向通信。举例:对讲机。
- 全双工数据通信允许数据同时在两个方向上传输;因此全双工通信是两个单工通信的结合,它要求发送设备和接收设备都有独立的接收和发送能力;在同一时间可以同时接受和发送信息,实现双向通信,举例:电话通信。