TCP/IP必知必会的10个问题 - Sanarous的博客

TCP/IP必知必会的10个问题

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 协议通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层不断地封装首部与尾部,添加一些传输的信息,确保能传输到目的地。出栈的过程,数据接收方每层不断地拆除首部与尾部,得到最终传输的数据。

上图以HTTP协议为例,具体说明。

数据链路层

物理层负责 0、1 比特流与物理设备电压高低、光的闪灭之间的互换。 数据链路层负责将 0、1 序列划分为数据帧从一个节点传输到临近的另一个节点,这些节点是通过 MAC 来唯一标识的(MAC,物理地址,一个主机会有一个 MAC 地址)。

  • 封装成帧: 把网络层数据报加头和尾,封装成帧,帧头中包括源 MAC 地址和目的 MAC 地址。
  • 透明传输:零比特填充、转义字符。
  • 可靠传输: 在出错率很低的链路上很少用,但是无线链路 WLAN 会保证可靠传输。
  • 差错检测(CRC):接收者检测错误,如果发现差错,丢弃该帧。

网络层

IP协议

IP 协议是 TCP/IP 协议的核心,所有的 TCP,UDP,IMCP,IGMP 的数据都以 IP 数据格式传输。要注意的是,IP 不是可靠的协议,这是说,IP 协议没有提供一种数据未传达以后的处理机制,这被认为是上层协议:TCP 或 UDP 要做的事情。

在数据链路层中我们一般通过MAC地址来识别不同的节点,而在IP层我们也要有一个类似的地址标识,这就是IP地址。

32 位IP地址分为网络位和地址位,这样做可以减少路由器中路由表记录的数目,有了网络地址,就可以限定拥有相同网络地址的终端都在同一个范围内,那么路由表只需要维护一条这个网络地址的方向,就可以找到相应的这些终端了。

A 类 IP 地址:0.0.0.0~127.0.0.0
B 类 IP 地址:128.0.0.1~191.255.0.0
C 类 IP 地址:192.168.0.0~239.255.255.0

IP 协议头如下:

这里只介绍八位的 TTL 字段。这个字段规定该数据包在穿过多少个路由之后才会被抛弃。某个 IP 数据包每穿过一个路由器,该数据包的 TTL 数值就会减少 1,当该数据包的TTL成为零,它就会被自动抛弃。

这个字段的最大值也就是 255,也就是说一个协议包也就在路由器里面穿行 255 次就会被抛弃了,根据系统的不同,这个数字也不一样,一般是 32 或者是 64。

ARP及RARP协议

ARP 是根据 IP 地址获取 MAC 地址的一种协议。

ARP(地址解析)协议是一种解析协议,本来主机是完全不知道这个 IP 对应的是哪个主机的哪个接口,当主机要发送一个 IP 包的时候,会首先查一下自己的ARP高速缓存(就是一个 IP-MAC 地址对应表缓存)。

如果查询的 IP-MAC 值对不存在,那么主机就向网络发送一个 ARP 协议广播包,这个广播包里面就有待查询的 IP 地址,而直接收到这份广播的包的所有主机都会查询自己的 IP 地址,如果收到广播包的某一个主机发现自己符合条件,那么就准备好一个包含自己的 MAC 地址的 ARP 包传送给发送 ARP 广播的主机。

而广播主机拿到 ARP 包后会更新自己的 ARP 缓存(就是存放 IP-MAC 对应表的地方)。发送广播的主机就会用新的 ARP 缓存数据准备好数据链路层的的数据包发送工作。

RARP 协议的工作与此相反,不做赘述。

ICMP协议

IP 协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成。其中一个重要的模块就是 ICMP(网络控制报文)协议。ICMP 不是高层协议,而是 IP 层的协议。

当传送 IP 数据包发生错误。比如主机不可达,路由不可达等等,ICMP 协议将会把错误信息封包,然后传送回给主机。给主机一个处理错误的机会,这 也就是为什么说建立在 IP 层以上的协议是可能做到安全的原因。

Ping

ping 可以说是 ICMP 的最著名的应用,是 TCP/IP 协议的一部分。利用 ping 命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。

例如:当我们某一个网站上不去的时候。通常会 ping 一下这个网站。ping 会回显出一些有用的信息。一般的信息如下:

ping 这个单词源自声纳定位,而这个程序的作用也确实如此,它利用 ICMP 协议包来侦测另一个主机是否可达。原理是用类型码为 0 的 ICMP 发请 求,受到请求的主机则用类型码为 8 的 ICMP 回应。

ping 程序来计算间隔时间,并计算有多少个包被送达。用户就可以判断网络大致的情况。我们可以看到, ping 给出来了传送的时间和 TTL 的数据。

Traceroute

Traceroute 是用来侦测主机到目的主机之间所经路由情况的重要工具,也是最便利的工具。

Traceroute 的原理是非常非常的有意思,它收到到目的主机的 IP 后,首先给目的主机发送一个 TTL=1 的 UDP 数据包,而经过的第一个路由器收到这个数据包以后,就自动把 TTL 减 1,而 TTL 变为 0 以后,路由器就把这个包给抛弃了,并同时产生 一个主机不可达的 ICMP 数据报给主机。主机收到这个数据报以后再发一个 TTL=2 的 UDP 数据报给目的主机,然后刺激第二个路由器给主机发 ICMP 数据报。如此往复直到到达目的主机。这样,traceroute 就拿到了所有的路由器 IP。

TCP/UDP

TCP/UDP 都是是传输层协议,但是两者具有不同的特性,同时也具有不同的应用场景。

  • 用户数据报协议 UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信。
  • 传输控制协议 TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。

面向报文

面向报文的传输方式是应用层交给 UDP 多长的报文,UDP 就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则 IP 层需要分片,降低效率。若太短,会是 IP 太小。

面向字节流

面向字节流的话,虽然应用程序和 TCP 的交互是一次一个数据块(大小不等),但 TCP 把应用程序看成是一连串的无结构的字节流。TCP 有一个缓冲,当应用程序传送的数据块太长,TCP 就可以把它划分短一些再传送。

关于拥塞控制,流量控制,是 TCP 的重点,后面讲解。

什么时候应该使用TCP

当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如 HTTP、HTTPS、FTP 等传输文件的协议,POP、SMTP 等邮件传输的协议。

什么时候应该使用UDP

当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用 UDP,比如网络直播。

DNS

DNS(Domain Name System,域名系统),因特网上作为域名和 IP 地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 IP 数串。通过主机名,最终得到该主机名对应的 IP 地址的过程叫做域名解析(或主机名解析)。DNS 协议运行在 UDP 协议之上,使用端口号 53。

TCP连接的建立与终止

三次握手

TCP 是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在 TCP/IP 协议中, TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。

假设 A 为客户端,B 为服务器端。

  • 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
  • A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。
  • B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。
  • A 收到 B 的连接确认报文后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。
  • B 收到 A 的确认后,连接建立。

三次握手的原因

第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。

客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。

四次挥手

以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

  • A 发送连接释放报文,FIN=1。
  • B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
  • 当 B 不再需要连接时,发送连接释放报文,FIN=1。
  • A 收到后发出确认,进入 TIME-WAIT 状态,等待 2 MSL(最大报文存活时间)后释放连接。
  • B 收到 A 的确认后释放连接。

四次挥手的原因

客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器会发送 FIN 连接释放报文。

TIME_WAIT

客户端接收到服务器端的 FIN 报文后进入此状态,此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:

  • 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。
  • 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。

TCP流量控制

如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

利用滑动窗口机制可以很方便地在 TCP 连接上实现对发送方的流量控制。

滑动窗口

窗口是缓存的一部分,用来暂时存放字节流。发送方和接收方各有一个窗口,接收方通过 TCP 报文段中的窗口字段告诉发送方自己的窗口大小,发送方根据这个值和其它信息设置自己的窗口大小。

发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。

接收窗口只会对窗口内最后一个按序到达的字节进行确认(累积确认),例如接收窗口已经收到的字节为 {31, 34, 35},其中 {31} 按序到达,而 {34, 35} 就不是,因此只对字节 31 进行确认。发送方得到一个字节的确认之后,就知道这个字节之前的所有字节都已经被接收。

TCP拥塞控制

如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。

TCP 主要通过四个算法来进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。

发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量,注意拥塞窗口与发送方窗口的区别:拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。

为了便于讨论,做如下假设:

  • 接收方有足够大的接收缓存,因此不会发生流量控制;
  • 虽然 TCP 的窗口基于字节,但是这里设窗口的大小单位为报文段。

慢开始与拥塞避免

发送的最初执行慢开始,令 cwnd = 1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 加倍,因此之后发送方能够发送的报文段数量为:2、4、8 …

注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能性也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免,每个轮次只将 cwnd 加 1。

如果出现了超时,则令 ssthresh = cwnd / 2,然后重新执行慢开始。

快重传与快恢复

在接收方,要求每次接收到报文段都应该对最后一个已收到的有序报文段进行确认。例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。

在发送方,如果收到三个重复确认,那么可以知道下一个报文段丢失,此时执行快重传,立即重传下一个报文段。例如收到三个 M2,则 M3 丢失,立即重传 M3。

在这种情况下,只是丢失个别报文段,而不是网络拥塞。因此执行快恢复,令 ssthresh = cwnd / 2 ,cwnd = ssthresh,注意到此时直接进入拥塞避免。

慢开始和快恢复的快慢指的是 cwnd 的设定值,而不是 cwnd 的增长速率。慢开始 cwnd 设定为 1,而快恢复 cwnd 设定为 ssthresh。

如果这篇文章对您很有帮助,不妨
-------------    本文结束  感谢您的阅读    -------------
0%